chiark / gitweb /
debian/changelog: start -4~
[vtwm.git] / util.c
1 /*****************************************************************************/
2 /**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
3 /**                          Salt Lake City, Utah                           **/
4 /**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
5 /**                        Cambridge, Massachusetts                         **/
6 /**                                                                         **/
7 /**                           All Rights Reserved                           **/
8 /**                                                                         **/
9 /**    Permission to use, copy, modify, and distribute this software and    **/
10 /**    its documentation  for  any  purpose  and  without  fee is hereby    **/
11 /**    granted, provided that the above copyright notice appear  in  all    **/
12 /**    copies and that both  that  copyright  notice  and  this  permis-    **/
13 /**    sion  notice appear in supporting  documentation,  and  that  the    **/
14 /**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
15 /**    in publicity pertaining to distribution of the  software  without    **/
16 /**    specific, written prior permission.                                  **/
17 /**                                                                         **/
18 /**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
19 /**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
20 /**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
21 /**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
22 /**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
23 /**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
24 /**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
25 /**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
26 /*****************************************************************************/
27
28 /*
29
30 Portions Copyright 1989, 1998  The Open Group
31
32 Permission to use, copy, modify, distribute, and sell this software and its
33 documentation for any purpose is hereby granted without fee, provided that
34 the above copyright notice appear in all copies and that both that
35 copyright notice and this permission notice appear in supporting
36 documentation.
37
38 The above copyright notice and this permission notice shall be included in
39 all copies or substantial portions of the Software.
40
41 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
44 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
45 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
46 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
47
48 Except as contained in this notice, the name of The Open Group shall not be
49 used in advertising or otherwise to promote the sale, use or other dealings
50 in this Software without prior written authorization from The Open Group.
51
52 */
53
54
55 /***********************************************************************
56  *
57  * $XConsortium: util.c,v 1.47 91/07/14 13:40:37 rws Exp $
58  *
59  * utility routines for twm
60  *
61  * 28-Oct-87 Thomas E. LaStrange        File created
62  *
63  ***********************************************************************/
64
65 #include "twm.h"
66 #include "util.h"
67 #include "gram.h"
68 #include "screen.h"
69 #include "list.h"
70 #include <X11/Xos.h>
71 #include <X11/Xatom.h>
72 #include <X11/Xmu/Drawing.h>
73 #include <X11/Xmu/CharSet.h>
74 #ifndef NO_XPM_SUPPORT
75 #include <X11/xpm.h>
76 #endif
77
78 #include <stdio.h>
79 #include <string.h>
80
81 /* see Zoom() - djhjr - 10/11/01 */
82 #ifdef NEED_SELECT_H
83 #include <sys/select.h>
84 #else
85 #include <sys/time.h>
86 #include <sys/types.h>
87 #endif
88 #ifndef ZOOMSLEEP
89 #define ZOOMSLEEP 50000 /* arbitrary, but pleasing, msec value */
90 #endif
91
92 /*
93  * All instances of Scr->TitleBevelWidth and Scr->BorderBevelWidth
94  * were a hard value of 2 - djhjr - 4/29/98
95  */
96
97 /* djhjr - 4/18/96 10/29/02 */
98 static void Draw3DMenuImage();
99 static void Draw3DDotImage();
100 static void Draw3DResizeImage();
101 static void Draw3DZoomImage();
102 static void Draw3DBarImage();
103
104 /* djhjr - 6/4/00 10/29/02 */
105 static void Draw3DRArrowImage();
106 static void Draw3DDArrowImage();
107
108 /* djhjr - 1/13/98 10/20/02 */
109 void setBorderGC();
110 #ifdef USE_ORIGINAL_CORNERS
111 void Draw3DCorner();
112 #else
113 GC setBevelGC();
114 void Draw3DBevel();
115 void Draw3DNoBevel();
116 #endif
117
118 /* djhjr - 4/19/96 */
119 static GC     rootGC = (GC) 0;
120
121 /* for trying to clean up BeNiceToColormap - djhjr - 10/20/02 */
122 static int borderdashoffset;
123
124 int HotX, HotY;
125
126 #define questionmark_width 8
127 #define questionmark_height 8
128 static unsigned char questionmark_bits[] = {
129    0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18};
130
131 /***********************************************************************
132  *
133  *  Procedure:
134  *      MoveOutline - move a window outline
135  *
136  *  Inputs:
137  *      root        - the window we are outlining
138  *      x           - upper left x coordinate
139  *      y           - upper left y coordinate
140  *      width       - the width of the rectangle
141  *      height      - the height of the rectangle
142  *      bw          - the border width of the frame
143  *      th          - title height
144  *
145  ***********************************************************************
146  */
147
148 /* ARGSUSED */
149 void MoveOutline(root, x, y, width, height, bw, th)
150     Window root;
151     int x, y, width, height, bw, th;
152 {
153     static int  lastx = 0;
154     static int  lasty = 0;
155     static int  lastWidth = 0;
156     static int  lastHeight = 0;
157     static int  lastBW = 0;
158     static int  lastTH = 0;
159     int         xl, xr, yt, yb, xinnerl, xinnerr, yinnert, yinnerb;
160     int         xthird, ythird;
161     XSegment    outline[18];
162     register XSegment   *r;
163
164     if (x == lastx && y == lasty && width == lastWidth && height == lastHeight
165         && lastBW == bw && th == lastTH)
166         return;
167
168     r = outline;
169
170 #ifdef ORIGINAL_DRAWIT
171 #define DRAWIT() \
172     if (lastWidth || lastHeight)                        \
173     {                                                   \
174         xl = lastx;                                     \
175         xr = lastx + lastWidth - 1;                     \
176         yt = lasty;                                     \
177         yb = lasty + lastHeight - 1;                    \
178         xinnerl = xl + lastBW;                          \
179         xinnerr = xr - lastBW;                          \
180         yinnert = yt + lastTH + lastBW;                 \
181         yinnerb = yb - lastBW;                          \
182         xthird = (xinnerr - xinnerl) / 3;               \
183         ythird = (yinnerb - yinnert) / 3;               \
184                                                         \
185         /* frame outline */                                             \
186         r->x1 = xl;                                     \
187         r->y1 = yt;                                     \
188         r->x2 = xr;                                     \
189         r->y2 = yt;                                     \
190         r++;                                            \
191                                                         \
192         r->x1 = xl;                                     \
193         r->y1 = yb;                                     \
194         r->x2 = xr;                                     \
195         r->y2 = yb;                                     \
196         r++;                                            \
197                                                         \
198         r->x1 = xl;                                     \
199         r->y1 = yt;                                     \
200         r->x2 = xl;                                     \
201         r->y2 = yb;                                     \
202         r++;                                            \
203                                                         \
204         r->x1 = xr;                                     \
205         r->y1 = yt;                                     \
206         r->x2 = xr;                                     \
207         r->y2 = yb;                                     \
208         r++;                                            \
209                                                         \
210         /* left vertical */                                             \
211         r->x1 = xinnerl + xthird;                       \
212         r->y1 = yinnert;                                \
213         r->x2 = r->x1;                                  \
214         r->y2 = yinnerb;                                \
215         r++;                                            \
216                                                         \
217         /* right vertical */                                            \
218         r->x1 = xinnerl + (2 * xthird);                 \
219         r->y1 = yinnert;                                \
220         r->x2 = r->x1;                                  \
221         r->y2 = yinnerb;                                \
222         r++;                                            \
223                                                         \
224         /* top horizontal */                                            \
225         r->x1 = xinnerl;                                \
226         r->y1 = yinnert + ythird;                       \
227         r->x2 = xinnerr;                                \
228         r->y2 = r->y1;                                  \
229         r++;                                            \
230                                                         \
231         /* bottom horizontal */                                         \
232         r->x1 = xinnerl;                                \
233         r->y1 = yinnert + (2 * ythird);                 \
234         r->x2 = xinnerr;                                \
235         r->y2 = r->y1;                                  \
236         r++;                                            \
237                                                         \
238         /* title bar */                                                         \
239         if (lastTH != 0) {                              \
240             r->x1 = xl;                                 \
241             r->y1 = yt + lastTH;                        \
242             r->x2 = xr;                                 \
243             r->y2 = r->y1;                              \
244             r++;                                        \
245         }                                               \
246     }
247
248     /* undraw the old one, if any */
249     DRAWIT ();
250
251     lastx = x;
252     lasty = y;
253     lastWidth = width;
254     lastHeight = height;
255     lastBW = bw;
256     lastTH = th;
257
258     /* draw the new one, if any */
259     DRAWIT ();
260 #else
261 #define DRAWIT() \
262     if (lastWidth || lastHeight)                        \
263     {                                                   \
264         xl = lastx;                                     \
265         xr = lastx + lastWidth - 1;                     \
266         yt = lasty;                                     \
267         yb = lasty + lastHeight - 1;                    \
268         xinnerl = xl + lastBW;                          \
269         xinnerr = xr - lastBW;                          \
270         yinnert = yt + lastTH + lastBW;                 \
271         yinnerb = yb - lastBW;                          \
272         xthird = (xinnerr - xinnerl) / 3;               \
273         ythird = (yinnerb - yinnert) / 3;               \
274                                                         \
275         /* frame outline */                                             \
276         r->x1 = xl;                                     \
277         r->y1 = yt;                                     \
278         r->x2 = xr;                                     \
279         r->y2 = yt;                                     \
280         r++;                                            \
281                                                         \
282         r->x1 = xl;                                     \
283         r->y1 = yb;                                     \
284         r->x2 = xr;                                     \
285         r->y2 = yb;                                     \
286         r++;                                            \
287                                                         \
288         r->x1 = xl;                                     \
289         r->y1 = yt;                                     \
290         r->x2 = xl;                                     \
291         r->y2 = yb;                                     \
292         r++;                                            \
293                                                         \
294         r->x1 = xr;                                     \
295         r->y1 = yt;                                     \
296         r->x2 = xr;                                     \
297         r->y2 = yb;                                     \
298         r++;                                            \
299                                                         \
300         /* top-left to bottom-right */          \
301         r->x1 = xinnerl;                        \
302         r->y1 = yinnert;                        \
303         r->x2 = xinnerr;                        \
304         r->y2 = yinnerb;                        \
305         r++;                            \
306                                                         \
307         /* bottom-left to top-right */          \
308         r->x1 = xinnerl;                        \
309         r->y1 = yinnerb;                        \
310         r->x2 = xinnerr;                        \
311         r->y2 = yinnert;                        \
312         r++;                            \
313                                                         \
314         /* title bar */                                         \
315         if (lastTH != 0) {                              \
316             r->x1 = xl;                                 \
317             r->y1 = yt + lastTH;                        \
318             r->x2 = xr;                                 \
319             r->y2 = r->y1;                              \
320             r++;                                        \
321         }                                               \
322     }
323
324     /* undraw the old one, if any */
325     DRAWIT ();
326
327     lastx = x;
328     lasty = y;
329     lastWidth = width;
330     lastHeight = height;
331     lastBW = bw;
332     lastTH = th;
333
334     /* draw the new one, if any */
335     DRAWIT ();
336 #endif
337
338 #undef DRAWIT
339
340     if (r != outline)
341     {
342         XDrawSegments(dpy, root, Scr->DrawGC, outline, r - outline);
343     }
344 }
345
346 /***********************************************************************
347  *
348  *  Procedure:
349  *      Zoom - zoom in or out of an icon
350  *
351  *  Inputs:
352  *      wf      - window to zoom from
353  *      ipf     - icon manager of window to zoom from
354  *      wt      - window to zoom to
355  *      ipt     - icon manager of window to zoom to
356  *
357  *      Patched to make sure a "None" window generates coordinates *INSIDE*
358  *      the screen. -- DSE 
359  *
360  *      Added args to icon managers so zooms from and to the window's
361  *      entry use that icon manager's coordinates - djhjr - 10/11/01 
362  *
363  ***********************************************************************
364  */
365
366 void
367 Zoom(wf, ipf, wt, ipt)
368     Window wf, wt;
369     IconMgr *ipf, *ipt;
370 {
371     int fx, fy, tx, ty;                 /* from, to */
372     unsigned int fw, fh, tw, th;        /* from, to */
373     long dx, dy, dw, dh;
374     long z;
375     int j;
376
377     /* djhjr - 10/11/01 */
378     static struct timeval timeoutval = {0, ZOOMSLEEP};
379     struct timeval timeout;
380     
381     void draw_rect(); /* DSE */
382     
383     if (!Scr->DoZoom || Scr->ZoomCount < 1) return;
384
385 #if (0)
386     if (wf == None || wt == None) return;
387
388     XGetGeometry (dpy, wf, &JunkRoot, &fx, &fy, &fw, &fh, &JunkBW, &JunkDepth);
389     XGetGeometry (dpy, wt, &JunkRoot, &tx, &ty, &tw, &th, &JunkBW, &JunkDepth);
390 #else
391
392     /* if (wf == None && wt == None) return; */
393
394         if ( wt == None)
395                 {
396                 if (Scr->LessRandomZoomZoom) /* DSE */
397                         {
398                         int temp,x1,y1,x2,y2;
399                         x1 = ( (int)rand() % (Scr->MyDisplayWidth >> 3) );
400                         x2 = Scr->MyDisplayWidth - 
401                                ( (int)rand() % (Scr->MyDisplayWidth >> 3) );
402                         y1 = ( (int)rand() % (Scr->MyDisplayHeight >> 3) );
403                         y2 = Scr->MyDisplayHeight - 
404                                ( (int)rand() % (Scr->MyDisplayHeight >> 3) );
405                         if(x1>x2){temp=x1;x1=x2;x2=temp;}
406                         if(y1>y2){temp=y1;y1=y2;y2=temp;}
407                         tx = x1; ty = y1;
408                         tw = x2 - x1; th = y2 - y1;
409                         }
410                 else
411                         {
412                         /* Zoom from nowhere, RFBZOOM */
413                         tx = ( (int)rand() % Scr->MyDisplayWidth );
414                         tw = ( (int)rand() % Scr->MyDisplayWidth );
415                         ty = ( (int)rand() % Scr->MyDisplayWidth );
416                         th = ( (int)rand() % Scr->MyDisplayWidth );
417                         }
418                 }
419         else
420                 {       /* Normal. */
421                 XGetGeometry (dpy, wt, &JunkRoot,
422                         &tx, &ty, &tw, &th, &JunkBW, &JunkDepth);
423
424                 if (ipt)
425                 {
426                         tx += (ipt->twm_win->frame_x + ipt->twm_win->title_x);
427                         ty += (ipt->twm_win->frame_y + ipt->twm_win->title_y +
428                                         ipt->twm_win->title_height);
429                 }
430                 }
431
432         if ( wf == None )
433                 {
434                 if (Scr->LessRandomZoomZoom) /* DSE */
435                         {
436                         /* zoom from somewhere on the screen, DSE */
437                         int temp,x1,y1,x2,y2;
438                         do
439                                 {
440                                 x1 = ( (int)rand() % Scr->MyDisplayWidth );
441                                 x2 = ( (int)rand() % Scr->MyDisplayWidth );
442                                 y1 = ( (int)rand() % Scr->MyDisplayHeight );
443                                 y2 = ( (int)rand() % Scr->MyDisplayHeight );
444                                 if(x1>x2){temp=x1;x1=x2;x2=temp;}
445                                 if(y1>y2){temp=y1;y1=y2;y2=temp;}
446                                 fx = x1; fy = y1;
447                                 fw = x2 - x1; fh = y2 - y1;
448                                 }
449                         while ( fw > (Scr->MyDisplayWidth >> 2) || fh > (Scr->MyDisplayHeight >> 2) );
450                         }
451                 else
452                         {
453                         /* Zoom from nowhere, RFB */
454                         /* fx = ( rand() & 1 ) * Scr->MyDisplayWidth; */
455                         fx = ( (int)rand() % Scr->MyDisplayWidth );
456                         fw = ( (int)rand() % Scr->MyDisplayWidth );
457                         fy = ( (int)rand() % Scr->MyDisplayWidth );
458                         fh = ( (int)rand() % Scr->MyDisplayWidth );
459                         }
460                 }
461
462         else
463                 {       /* Normal. */
464                 XGetGeometry (dpy, wf, &JunkRoot,
465                         &fx, &fy, &fw, &fh, &JunkBW, &JunkDepth);
466
467                 if (ipf)
468                 {
469                         fx += (ipf->twm_win->frame_x + ipf->twm_win->title_x);
470                         fy += (ipf->twm_win->frame_y + ipf->twm_win->title_y +
471                                         ipf->twm_win->title_height);
472                 }
473                 }
474 #endif
475
476     dx = ((long) (tx - fx));    /* going from -> to */
477     dy = ((long) (ty - fy));    /* going from -> to */
478     dw = ((long) (tw - fw));    /* going from -> to */
479     dh = ((long) (th - fh));    /* going from -> to */
480     z = (long) (Scr->ZoomCount + 1);
481
482     for (j = 0; j < 2; j++) {
483         long i;
484
485         draw_rect (dpy, Scr->Root, Scr->DrawGC, fx, fy, fw, fh); /* DSE */
486         for (i = 1; i < z; i++)
487                 {
488             int x = fx + (int) ((dx * i) / z);
489             int y = fy + (int) ((dy * i) / z);
490             unsigned width = (unsigned) (((long) fw) + (dw * i) / z);
491             unsigned height = (unsigned) (((long) fh) + (dh * i) / z);
492
493             draw_rect (dpy, Scr->Root, Scr->DrawGC, x, y, width, height); /* DSE */
494                 }
495         draw_rect (dpy, Scr->Root, Scr->DrawGC, tx, ty, tw, th); /* DSE */
496
497         /* djhjr - 10/11/01 */
498         timeout = timeoutval;
499         select(0, 0, 0, 0, &timeout);
500     }
501 }
502
503
504 /*
505  *      Use any routine to draw your own rectangles here. -- DSE
506  */
507 void draw_rect (display,drawable,gc,x,y,width,height) /* DSE */
508                 Display *display;
509                 Drawable drawable;
510                 GC gc;
511                 int x,y;
512                 unsigned int width,height;
513         {
514         void draw_scaled_rect();
515         draw_scaled_rect (display,drawable,gc,x,y,width,height, 20,20);
516         if (Scr->PrettyZoom)
517                 {
518                 draw_scaled_rect (display,drawable,gc,x,y,width,height, 18,20);
519                 draw_scaled_rect (display,drawable,gc,x,y,width,height, 16,20);
520                 }
521         }
522 void draw_scaled_rect (display,drawable,gc,x,y,
523                        width,height,scale,over) /* DSE */
524                 Display *display;
525                 Drawable drawable;
526                 GC gc;
527                 int x,y;
528                 unsigned int width,height;
529                 unsigned int scale,over;
530         {
531         XDrawRectangle(dpy,drawable,gc,
532                 x + ( over + width * (over - scale) ) / (2 * over),
533                   y + ( over  + width * (over - scale) ) / (2 * over),
534                 ( (over / 2) + width * scale ) / over,
535                   ( (over / 2) + height * scale ) / over
536                 );
537         }
538
539 /***********************************************************************
540  *
541  *  Procedure:
542  *      ExpandFilename - expand the tilde character to HOME
543  *              if it is the first character of the filename
544  *
545  *  Returned Value:
546  *      a pointer to the new name
547  *
548  *  Inputs:
549  *      name    - the filename to expand
550  *
551  ***********************************************************************
552  */
553
554 char *
555 ExpandFilename(name)
556 char *name;
557 {
558     char *newname;
559
560     if (name[0] != '~') return name;
561
562     newname = (char *) malloc (HomeLen + strlen(name) + 2);
563     if (!newname) {
564         fprintf (stderr,
565                  "%s:  unable to allocate %d bytes to expand filename %s/%s\n",
566                  ProgramName, HomeLen + strlen(name) + 2, Home, &name[1]);
567     } else {
568         (void) sprintf (newname, "%s/%s", Home, &name[1]);
569     }
570
571     return newname;
572 }
573
574 /***********************************************************************
575  *
576  *  Procedure:
577  *      GetUnknownIcon - read in the bitmap file for the unknown icon
578  *
579  *  Inputs:
580  *      name - the filename to read
581  *
582  ***********************************************************************
583  */
584
585 void
586 GetUnknownIcon(name)
587 char *name;
588 {
589 /* djhjr - 8/13/98 */
590 #ifdef ORIGINAL_PIXMAPS
591     if ((Scr->UnknownPm = GetBitmap(name)) != None)
592     {
593         XGetGeometry(dpy, Scr->UnknownPm, &JunkRoot, &JunkX, &JunkY,
594             (unsigned int *)&Scr->UnknownWidth, (unsigned int *)&Scr->UnknownHeight, &JunkBW, &JunkDepth);
595     }
596 #else
597         Scr->unknownName = name;
598 #endif
599 }
600
601 /***********************************************************************
602  *
603  *  Procedure:
604  *      FindBitmap - read in a bitmap file and return size
605  *
606  *  Returned Value:
607  *      the pixmap associated with the bitmap
608  *      widthp  - pointer to width of bitmap
609  *      heightp - pointer to height of bitmap
610  *
611  *  Inputs:
612  *      name    - the filename to read
613  *
614  ***********************************************************************
615  */
616
617 Pixmap FindBitmap (name, widthp, heightp)
618     char *name;
619     unsigned int *widthp, *heightp;
620 {
621     char *bigname;
622     Pixmap pm;
623
624     if (!name) return None;
625
626     /*
627      * Generate a full pathname if any special prefix characters (such as ~)
628      * are used.  If the bigname is different from name, bigname will need to
629      * be freed.
630      */
631     bigname = ExpandFilename (name);
632     if (!bigname) return None;
633
634     /*
635      * look along bitmapFilePath resource same as toolkit clients
636      */
637     pm = XmuLocateBitmapFile (ScreenOfDisplay(dpy, Scr->screen), bigname, NULL,
638                               0, (int *)widthp, (int *)heightp, &HotX, &HotY);
639     if (pm == None && Scr->IconDirectory && bigname[0] != '/') {
640         if (bigname != name) free (bigname);
641         /*
642          * Attempt to find icon in old IconDirectory (now obsolete)
643          */
644         bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) +
645                                    2);
646         if (!bigname) {
647             fprintf (stderr,
648                      "%s:  unable to allocate memory for \"%s/%s\"\n",
649                      ProgramName, Scr->IconDirectory, name);
650             return None;
651         }
652         (void) sprintf (bigname, "%s/%s", Scr->IconDirectory, name);
653         if (XReadBitmapFile (dpy, Scr->Root, bigname, widthp, heightp, &pm,
654                              &HotX, &HotY) != BitmapSuccess) {
655             pm = None;
656         }
657     }
658     if (bigname != name) free (bigname);
659
660 #ifdef DEBUG
661     if (pm == None) {
662         fprintf (stderr, "%s:  unable to find bitmap \"%s\"\n",
663                  ProgramName, name);
664     }
665 #endif
666
667     return pm;
668 }
669
670 Pixmap GetBitmap (name)
671     char *name;
672 {
673     return FindBitmap (name, &JunkWidth, &JunkHeight);
674 }
675
676 #ifndef NO_XPM_SUPPORT
677 /*
678  * Submitted by Jason Gloudon
679  * added color argument - djhjr - 9/28/99
680  */
681 Image *FindImage (name, color)
682     char *name;
683     Pixel color;
684 {
685     char *bigname;
686     Pixmap pixmap,mask;
687     Image *newimage = None; /* added intialization - djhjr - 3/21/98 */
688     XpmAttributes attributes;
689         XpmColorSymbol xpmcolor[1]; /* djhjr - 9/28/99 */
690     int ErrorStatus;
691     
692     /*
693      * Generate a full pathname if any special prefix characters (such as ~)
694      * are used.  If the bigname is different from name, bigname will need to
695      * be freed.
696      */
697     bigname = ExpandFilename (name);
698     if (!bigname) return None;
699
700     /* was 'XpmReturnAllocPixels' - Submitted by Takeharu Kato */
701     attributes.valuemask = XpmReturnPixels;
702
703     /* djhjr - 5/10/99 */
704     attributes.valuemask |= XpmCloseness;
705     attributes.closeness = 32768;
706
707         /* djhjr - 9/28/99 */
708         if (color)
709         {
710                 xpmcolor[0].name = NULL;
711                 xpmcolor[0].value = "none";
712                 xpmcolor[0].pixel = color;
713
714                 attributes.colorsymbols = xpmcolor;
715                 attributes.numsymbols = 1;
716                 attributes.valuemask |= XpmColorSymbols;
717         }
718
719     /*
720      * By default, the XPM library assumes screen 0, so we have
721      * to pass in the real values. Submitted by Caveh Frank Jalali
722      */
723     attributes.valuemask |= XpmVisual | XpmColormap | XpmDepth;
724     attributes.visual = Scr->d_visual;
725     attributes.colormap = XDefaultColormap(dpy, Scr->screen);
726     attributes.depth = Scr->d_depth;
727
728     if( (ErrorStatus = XpmReadFileToPixmap(dpy, Scr->Root, bigname, &pixmap,
729                                            &mask, &attributes)) != XpmSuccess){
730       pixmap = None;
731     }
732
733         /*
734          * Do for pixmaps what XmuLocateBitmapFile() does for bitmaps,
735          * because, apparently, XmuLocatePixmapFile() doesn't!
736          *
737          * djhjr - 12/26/98
738          */
739         if (pixmap == None && Scr->BitmapFilePath && bigname[0] != '/')
740         {
741                 char *path = Scr->BitmapFilePath, *term;
742
743                 do
744                 {
745                         if ((term = strchr(path, ':'))) *term = 0;
746
747                         if (bigname != name) free(bigname);
748                         if (!(bigname = (char *)malloc(strlen(name) + strlen(path) + 2)))
749                                 fprintf(stderr, "%s:  unable to allocate memory for \"%s/%s\"\n",
750                                                 ProgramName, path, name);
751                         else
752                         {
753                                 (void)sprintf(bigname, "%s/%s", path, name);
754
755 #ifdef NEVER /* once, at the top, is enough? - djhjr - 12/26/98 */
756                                 /* was 'XpmReturnAllocPixels' - Submitted by Takeharu Kato */
757                                 attributes.valuemask = XpmReturnPixels;
758
759                                 /* djhjr - 5/10/99 */
760                                 attributes.valuemask |= XpmCloseness;
761                                 attributes.closeness = 32768;
762
763                                 /* djhjr - 9/28/99 */
764                                 if (color)
765                                 {
766                                         xpmcolor[0].name = NULL;
767                                         xpmcolor[0].value = "none";
768                                         xpmcolor[0].pixel = color;
769
770                                         attributes.colorsymbols = xpmcolor;
771                                         attributes.numsymbols = 1;
772                                         attributes.valuemask |= XpmColorSymbols;
773                                 }
774
775                                 /*
776                                  * By default, the XPM library assumes screen 0, so we have
777                                  * to pass in the real values. Submitted by Caveh Frank Jalali
778                                  */
779                                 attributes.valuemask |= XpmVisual | XpmColormap | XpmDepth;
780                                 attributes.visual = Scr->d_visual;
781                                 attributes.colormap = XDefaultColormap(dpy, Scr->screen);
782                                 attributes.depth = Scr->d_depth;
783 #endif /* NEVER */
784
785                                 ErrorStatus = XpmReadFileToPixmap(dpy, Scr->Root, bigname,
786                                                 &pixmap, &mask, &attributes);
787                         }
788
789                         if (term)
790                         {
791                                 *term = ':';
792                                 path = term + 1;
793                         }
794                         else
795                                 path = NULL;
796
797                         if (ErrorStatus != XpmSuccess)
798                                 pixmap = None;
799                         else
800                                 break;
801
802                 } while (path);
803         }
804
805     if (pixmap == None && Scr->IconDirectory && bigname[0] != '/') {
806       if (bigname != name) free (bigname);
807       /*
808        * Attempt to find icon pixmap in old IconDirectory (now obsolete)
809        */
810       bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) + 2);
811       if (!bigname) {
812         fprintf (stderr,
813                  "%s:  unable to allocate memory for \"%s/%s\"\n",
814                  ProgramName, Scr->IconDirectory, name);
815         return None;
816       }
817       (void) sprintf (bigname, "%s/%s", Scr->IconDirectory, name);
818
819 #ifdef NEVER /* once, at the top, is enough? - djhjr - 12/26/98 */
820       /* was 'XpmReturnAllocPixels' - Submitted by Takeharu Kato */
821       attributes.valuemask = XpmReturnPixels;
822
823       /* djhjr - 5/10/99 */
824       attributes.valuemask |= XpmCloseness;
825       attributes.closeness = 32768;
826
827       /*
828        * By default, the XPM library assumes screen 0, so we have
829        * to pass in the real values. Submitted by Caveh Frank Jalali
830        */
831       attributes.valuemask |= XpmVisual | XpmColormap | XpmDepth;
832       attributes.visual = Scr->d_visual;
833       attributes.colormap = XDefaultColormap(dpy, Scr->screen);
834       attributes.depth = Scr->d_depth;
835 #endif /* NEVER */
836
837       ErrorStatus = XpmReadFileToPixmap(dpy, Scr->Root, bigname, &pixmap,
838                                         &mask, &attributes);
839     }
840
841     if(ErrorStatus == XpmSuccess){
842       newimage = (Image *)malloc(sizeof(Image));
843       newimage->pixmap = pixmap;
844       newimage->mask = mask;
845       newimage->height = attributes.height;
846       newimage->width = attributes.width;
847     }
848     else {
849       fprintf (stderr, "%s:  unable to find pixmap \"%s\"\n",
850                ProgramName, name);
851     }
852
853     if (bigname != name) free (bigname);
854     return newimage;
855 }
856 #endif /* NO_XPM_SUPPORT */
857
858 void InsertRGBColormap (a, maps, nmaps, replace)
859     Atom a;
860     XStandardColormap *maps;
861     int nmaps;
862     Bool replace;
863 {
864     StdCmap *sc = NULL;
865
866     if (replace) {                      /* locate existing entry */
867         for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
868             if (sc->atom == a) break;
869         }
870     }
871
872     if (!sc) {                          /* no existing, allocate new */
873         sc = (StdCmap *) malloc (sizeof (StdCmap));
874         if (!sc) {
875             fprintf (stderr, "%s:  unable to allocate %d bytes for StdCmap\n",
876                      ProgramName, sizeof (StdCmap));
877             return;
878         }
879     }
880
881     if (replace) {                      /* just update contents */
882         if (sc->maps) XFree ((char *) maps);
883         if (sc == Scr->StdCmapInfo.mru) Scr->StdCmapInfo.mru = NULL;
884     } else {                            /* else appending */
885         sc->next = NULL;
886         sc->atom = a;
887         if (Scr->StdCmapInfo.tail) {
888             Scr->StdCmapInfo.tail->next = sc;
889         } else {
890             Scr->StdCmapInfo.head = sc;
891         }
892         Scr->StdCmapInfo.tail = sc;
893     }
894     sc->nmaps = nmaps;
895     sc->maps = maps;
896
897     return;
898 }
899
900 /*
901  * SetPixmapsPixmap - load the Image structure for the Pixmaps resource images
902  *
903  * djhjr - 5/17/98
904  */
905 Image *SetPixmapsPixmap(filename)
906 char *filename;
907 {
908         Pixmap bm;
909         Image *image = NULL;
910
911         bm = FindBitmap(filename, &JunkWidth, &JunkHeight);
912         if (bm != None)
913         {
914                 image = (Image *)malloc(sizeof(Image));
915             
916                 image->width = JunkWidth;
917                 image->height = JunkHeight;
918                 image->mask = None;
919
920                 image->pixmap = bm;
921         }
922 #ifndef NO_XPM_SUPPORT
923         else /* Try to find a pixmap file with this name */
924
925                 /* added color argument - djhjr - 9/28/99 */
926                 image = FindImage(filename, 0);
927 #endif
928
929         return image;
930 }
931
932 /*
933  * SetPixmapsBackground - set the background for the Pixmaps resource images
934  *
935  * djhjr - 5/23/98
936  * used to receive (int *)numcolors and return (Image *)image - djhjr - 9/2/98
937  */
938 #ifndef NO_XPM_SUPPORT
939 int SetPixmapsBackground(image, drawable, color)
940 Image *image;
941 Drawable drawable;
942 Pixel color;
943 {
944         XpmImage xpmimage;
945         XpmAttributes xpmattr;
946         XpmColorSymbol xpmcolor[1];
947         unsigned int i;
948
949         /* djhjr - 5/10/99 */
950         xpmattr.valuemask = XpmCloseness;
951         xpmattr.closeness = 32768;
952
953         /*
954          * By default, the XPM library assumes screen 0, so we have
955          * to pass in the real values. Submitted by Caveh Frank Jalali
956          */
957         xpmattr.valuemask |= XpmVisual | XpmColormap | XpmDepth;
958         xpmattr.visual = Scr->d_visual;
959         xpmattr.colormap = XDefaultColormap(dpy, Scr->screen);
960         xpmattr.depth = Scr->d_depth;
961
962         if (XpmCreateXpmImageFromPixmap(dpy, image->pixmap, image->mask,
963                         &xpmimage, &xpmattr) != XpmSuccess)
964                 return (0);
965
966         for (i = 0; i < xpmimage.ncolors; i++)
967                 if (!strcmp(xpmimage.colorTable[i].c_color, "None"))
968                         break;
969
970         if (i < xpmimage.ncolors)
971         {
972                 /* djhjr - 9/2/98 */
973                 XFreePixmap(dpy, image->pixmap);
974                 XFreePixmap(dpy, image->mask);
975
976                 xpmcolor[0].name = NULL;
977                 xpmcolor[0].value = "none";
978                 xpmcolor[0].pixel = color;
979
980 #ifdef NEVER /* once, at the top, is enough? - djhjr - 2/13/99 */
981                 xpmattr.colorsymbols = xpmcolor;
982                 xpmattr.numsymbols = 1;
983                 xpmattr.valuemask = XpmColorSymbols;
984
985                 /* djhjr - 5/10/99 */
986                 xpmattr.valuemask |= XpmCloseness;
987                 xpmattr.closeness = 32768;
988
989                 /*
990                  * By default, the XPM library assumes screen 0, so we have
991                  * to pass in the real values. Submitted by Caveh Frank Jalali
992                  */
993                 xpmattr.valuemask |= XpmVisual | XpmColormap | XpmDepth;
994                 xpmattr.visual = Scr->d_visual;
995                 xpmattr.colormap = XDefaultColormap(dpy, Scr->screen);
996                 xpmattr.depth = Scr->d_depth;
997 #else
998                 xpmattr.colorsymbols = xpmcolor;
999                 xpmattr.numsymbols = 1;
1000                 xpmattr.valuemask |= XpmColorSymbols;
1001 #endif /* NEVER */
1002
1003                 XpmCreatePixmapFromXpmImage(dpy, drawable, &xpmimage,
1004                                 &image->pixmap, &image->mask, &xpmattr);
1005         }
1006
1007         i = xpmimage.ncolors;
1008         XpmFreeXpmImage(&xpmimage);
1009
1010         return (i);
1011 }
1012 #endif /* NO_XPM_SUPPORT */
1013
1014 void RemoveRGBColormap (a)
1015     Atom a;
1016 {
1017     StdCmap *sc, *prev;
1018
1019     prev = NULL;
1020     for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
1021         if (sc->atom == a) break;
1022         prev = sc;
1023     }
1024     if (sc) {                           /* found one */
1025         if (sc->maps) XFree ((char *) sc->maps);
1026         if (prev) prev->next = sc->next;
1027         if (Scr->StdCmapInfo.head == sc) Scr->StdCmapInfo.head = sc->next;
1028         if (Scr->StdCmapInfo.tail == sc) Scr->StdCmapInfo.tail = prev;
1029         if (Scr->StdCmapInfo.mru == sc) Scr->StdCmapInfo.mru = NULL;
1030     }
1031     return;
1032 }
1033
1034 void LocateStandardColormaps()
1035 {
1036     Atom *atoms;
1037     int natoms;
1038     int i;
1039
1040     atoms = XListProperties (dpy, Scr->Root, &natoms);
1041     for (i = 0; i < natoms; i++) {
1042         XStandardColormap *maps = NULL;
1043         int nmaps;
1044
1045         if (XGetRGBColormaps (dpy, Scr->Root, &maps, &nmaps, atoms[i])) {
1046             /* if got one, then append to current list */
1047             InsertRGBColormap (atoms[i], maps, nmaps, False);
1048         }
1049     }
1050     if (atoms) XFree ((char *) atoms);
1051     return;
1052 }
1053
1054 void GetColor(kind, what, name)
1055 int kind;
1056 Pixel *what;
1057 char *name;
1058 {
1059     XColor color, junkcolor;
1060     Status stat = 0;
1061     Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c;
1062
1063 #ifndef TOM
1064     if (!Scr->FirstTime) return;
1065 #endif
1066
1067     if (Scr->Monochrome != kind) return;
1068
1069 #if ( XlibSpecificationRelease < 5 )
1070     /* eyckmans@imec.be */
1071         if ( ! ( ( name[0] == '#')
1072                         ? ( (stat = XParseColor (dpy, cmap, name, &color))
1073                                 && XAllocColor (dpy, cmap, &color))
1074                         : XAllocNamedColor (dpy, cmap, name, &color, &junkcolor)))
1075 #else
1076     if (!XAllocNamedColor (dpy, cmap, name, &color, &junkcolor))
1077 #endif
1078     {
1079         /* if we could not allocate the color, let's see if this is a
1080          * standard colormap
1081          */
1082         XStandardColormap *stdcmap = NULL;
1083
1084         /* parse the named color */
1085         if (name[0] != '#')
1086             stat = XParseColor (dpy, cmap, name, &color);
1087         if (!stat)
1088         {
1089             fprintf (stderr, "%s:  invalid color name \"%s\"\n",
1090                      ProgramName, name);
1091             return;
1092         }
1093
1094         /*
1095          * look through the list of standard colormaps (check cache first)
1096          */
1097         if (Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps &&
1098             (Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap ==
1099              cmap)) {
1100             stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]);
1101         } else {
1102             StdCmap *sc;
1103
1104             for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
1105                 int i;
1106
1107                 for (i = 0; i < sc->nmaps; i++) {
1108                     if (sc->maps[i].colormap == cmap) {
1109                         Scr->StdCmapInfo.mru = sc;
1110                         Scr->StdCmapInfo.mruindex = i;
1111                         stdcmap = &(sc->maps[i]);
1112                         goto gotit;
1113                     }
1114                 }
1115             }
1116         }
1117
1118       gotit:
1119         if (stdcmap) {
1120             color.pixel = (stdcmap->base_pixel +
1121                            ((Pixel)(((float)color.red / 65535.0) *
1122                                     stdcmap->red_max + 0.5) *
1123                             stdcmap->red_mult) +
1124                            ((Pixel)(((float)color.green /65535.0) *
1125                                     stdcmap->green_max + 0.5) *
1126                             stdcmap->green_mult) +
1127                            ((Pixel)(((float)color.blue  / 65535.0) *
1128                                     stdcmap->blue_max + 0.5) *
1129                             stdcmap->blue_mult));
1130         } else {
1131             fprintf (stderr, "%s:  unable to allocate color \"%s\"\n",
1132                      ProgramName, name);
1133             return;
1134         }
1135     }
1136
1137     *what = color.pixel;
1138 }
1139
1140 void GetShadeColors (cp)
1141 ColorPair *cp;
1142 {
1143     XColor      xcol;
1144     Colormap    cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c;
1145     int         save;
1146     float       clearfactor;
1147     float       darkfactor;
1148     char        clearcol [32], darkcol [32];
1149
1150     clearfactor = (float) Scr->ClearBevelContrast / 100.0;
1151     darkfactor  = (100.0 - (float) Scr->DarkBevelContrast)  / 100.0;
1152     xcol.pixel = cp->back;
1153     XQueryColor (dpy, cmap, &xcol);
1154
1155     sprintf (clearcol, "#%04x%04x%04x",
1156                 xcol.red   + (unsigned short) ((65535 -   xcol.red) * clearfactor),
1157                 xcol.green + (unsigned short) ((65535 - xcol.green) * clearfactor),
1158                 xcol.blue  + (unsigned short) ((65535 -  xcol.blue) * clearfactor));
1159     sprintf (darkcol,  "#%04x%04x%04x",
1160                 (unsigned short) (xcol.red   * darkfactor),
1161                 (unsigned short) (xcol.green * darkfactor),
1162                 (unsigned short) (xcol.blue  * darkfactor));
1163
1164     save = Scr->FirstTime;
1165     Scr->FirstTime = True;
1166     GetColor (Scr->Monochrome, &cp->shadc, clearcol);
1167     GetColor (Scr->Monochrome, &cp->shadd,  darkcol);
1168     Scr->FirstTime = save;
1169 }
1170
1171 /* 
1172  * The following I18N-oriented functions are adapted from TWM
1173  * as distributed with XFree86 4.2.0 - djhjr - 9/14/03
1174  */
1175
1176 /*
1177  * The following functions are sensible to 'use_fontset'.
1178  * When 'use_fontset' is True,
1179  *  - XFontSet-related internationalized functions are used
1180  *     so as multibyte languages can be displayed.
1181  * When 'use_fontset' is False,
1182  *  - XFontStruct-related conventional functions are used
1183  *     so as 8-bit characters can be displayed even when
1184  *     locale is not set properly.
1185  */
1186 void
1187 GetFont(font)
1188 MyFont *font;
1189 {
1190 #ifndef NO_I18N_SUPPORT
1191     char **missing_charset_list_return;
1192     int missing_charset_count_return;
1193     char *def_string_return;
1194     XFontSetExtents *font_extents;
1195     XFontStruct **xfonts;
1196     char **font_names;
1197     register int i;
1198     int ascent;
1199     int descent;
1200     int fnum;
1201     char *basename2, *basename3 = NULL;
1202
1203     if (use_fontset)
1204     {
1205         if (font->fontset != NULL)
1206             XFreeFontSet(dpy, font->fontset);
1207
1208         if (!font->name)
1209             font->name = Scr->DefaultFont.name;
1210         if ((basename2 = (char *)malloc(strlen(font->name) + 3)))
1211             sprintf(basename2, "%s,*", font->name);
1212         else
1213             basename2 = font->name;
1214         if ((font->fontset = XCreateFontSet(dpy, basename2,
1215                                             &missing_charset_list_return,
1216                                             &missing_charset_count_return,
1217                                             &def_string_return)) == NULL)
1218         {
1219             /* idea from Seth Robertson - djhjr - 9/17/03 */
1220
1221             if ((basename3 = (char *)realloc(basename2,
1222                                         strlen(Scr->DefaultFont.name) + 3)))
1223                 sprintf(basename3, "%s,*", Scr->DefaultFont.name);
1224             else
1225             {
1226                 basename3 = Scr->DefaultFont.name;
1227                 if (basename2 != font->name)
1228                     free(basename2);
1229             }
1230             if ((font->fontset = XCreateFontSet(dpy, basename3,
1231                                                 &missing_charset_list_return,
1232                                                 &missing_charset_count_return,
1233                                                 &def_string_return)) == NULL)
1234             {
1235                 fprintf(stderr,
1236                         "%s: unable to open fontsets \"%s\" or \"%s\"\n",
1237                         ProgramName, font->name, Scr->DefaultFont.name);
1238                 if (basename3 != Scr->DefaultFont.name)
1239                     free(basename3);
1240                 exit(1);
1241             }
1242             basename2 = basename3;
1243         }
1244
1245         if (basename2 != ((basename3) ? Scr->DefaultFont.name : font->name))
1246             free(basename2);
1247
1248         for (i = 0; i < missing_charset_count_return; i++)
1249             fprintf(stderr, "%s: font for charset %s is lacking\n",
1250                    ProgramName, missing_charset_list_return[i]);
1251
1252         font_extents = XExtentsOfFontSet(font->fontset);
1253         fnum = XFontsOfFontSet(font->fontset, &xfonts, &font_names);
1254         for (i = 0, ascent = 0, descent = 0; i<fnum; i++)
1255         {
1256             if (ascent < (*xfonts)->ascent)
1257                 ascent = (*xfonts)->ascent;
1258             if (descent < (*xfonts)->descent)
1259                 descent = (*xfonts)->descent;
1260             xfonts++;
1261         }
1262
1263         font->height = font_extents->max_logical_extent.height;
1264         font->y = ascent;
1265         font->ascent = ascent;
1266         font->descent = descent;
1267         return;
1268     }
1269 #endif
1270
1271     if (font->font != NULL)
1272         XFreeFont(dpy, font->font);
1273
1274     if ((font->font = XLoadQueryFont(dpy, font->name)) == NULL)
1275         if ((font->font = XLoadQueryFont(dpy, Scr->DefaultFont.name)) == NULL)
1276         {
1277             fprintf(stderr, "%s:  unable to open fonts \"%s\" or \"%s\"\n",
1278                     ProgramName, font->name, Scr->DefaultFont.name);
1279             exit(1);
1280         }
1281
1282     font->height = font->font->ascent + font->font->descent;
1283     font->y = font->font->ascent;
1284     font->ascent = font->font->ascent;
1285     font->descent = font->font->descent;
1286 }
1287
1288 #ifndef NO_I18N_SUPPORT
1289 int
1290 MyFont_TextWidth(font, string, len)
1291     MyFont *font;
1292     char *string;
1293     int len;
1294 {
1295     XRectangle ink_rect;
1296     XRectangle logical_rect;
1297
1298     if (use_fontset) {
1299         XmbTextExtents(font->fontset, string, len, &ink_rect, &logical_rect);
1300         return logical_rect.width;
1301     }
1302     return XTextWidth(font->font, string, len);
1303 }
1304
1305 void
1306 MyFont_DrawImageString(dpy, d, font, gc, x, y, string, len)
1307     Display *dpy;
1308     Drawable d;
1309     MyFont *font;
1310     GC gc;
1311     int x,y;
1312     char *string;
1313     int len;
1314 {
1315     if (use_fontset) {
1316         XmbDrawImageString(dpy, d, font->fontset, gc, x, y, string, len);
1317         return;
1318     }
1319     XDrawImageString (dpy, d, gc, x, y, string, len);
1320 }
1321
1322 void
1323 MyFont_DrawString(dpy, d, font, gc, x, y, string, len)
1324     Display *dpy;
1325     Drawable d;
1326     MyFont *font;
1327     GC gc;
1328     int x,y;
1329     char *string;
1330     int len;
1331 {
1332     if (use_fontset) {
1333         XmbDrawString(dpy, d, font->fontset, gc, x, y, string, len);
1334         return;
1335     }
1336     XDrawString (dpy, d, gc, x, y, string, len);
1337 }
1338
1339 void
1340 MyFont_ChangeGC(fix_fore, fix_back, fix_font)
1341     unsigned long fix_fore, fix_back;
1342     MyFont *fix_font;
1343 {
1344     Gcv.foreground = fix_fore;
1345     Gcv.background = fix_back;
1346     if (use_fontset) {
1347         XChangeGC(dpy, Scr->NormalGC, GCForeground|GCBackground, &Gcv);
1348         return;
1349     }
1350     Gcv.font = fix_font->font->fid;
1351     XChangeGC(dpy, Scr->NormalGC, GCFont|GCForeground|GCBackground,&Gcv);
1352 }
1353
1354 /*
1355  * The following functions are internationalized substitutions
1356  * for XFetchName and XGetIconName using XGetWMName and
1357  * XGetWMIconName.  
1358  *
1359  * Please note that the third arguments have to be freed using free(), 
1360  * not XFree().
1361  */
1362 Status
1363 I18N_FetchName(dpy, w, winname)
1364     Display *dpy;
1365     Window w;
1366     char ** winname;
1367 {
1368     int    status;
1369     XTextProperty text_prop;
1370     char **list;
1371     int    num;
1372     
1373     status = XGetWMName(dpy, w, &text_prop);
1374     if (!status || !text_prop.value || !text_prop.nitems) {
1375         *winname = NULL;
1376         return 0;
1377     }
1378     *winname = (char *)strdup(text_prop.value);
1379     status = XmbTextPropertyToTextList(dpy, &text_prop, &list, &num);
1380     if (status < Success || !num || !*list) {
1381         *winname = NULL;      
1382         return 0;
1383     }
1384     XFree(text_prop.value);
1385     *winname = (char *)strdup(*list);
1386     XFreeStringList(list);
1387     return 1;
1388 }
1389
1390 Status
1391 I18N_GetIconName(dpy, w, iconname)
1392     Display *dpy;
1393     Window w;
1394     char ** iconname;
1395 {
1396     int    status;
1397     XTextProperty text_prop;
1398     char **list;
1399     int    num;
1400         
1401     status = XGetWMIconName(dpy, w, &text_prop);
1402     if (!status || !text_prop.value || !text_prop.nitems) return 0;
1403     *iconname = (char *)strdup(text_prop.value);
1404     status = XmbTextPropertyToTextList(dpy, &text_prop, &list, &num);
1405     if (status < Success || !num || !*list) return 0;
1406     XFree(text_prop.value);
1407     *iconname = (char *)strdup(*list);
1408     XFreeStringList(list);
1409     return 1;
1410 }
1411 #endif
1412
1413
1414 /*
1415  * SetFocus - separate routine to set focus to make things more understandable
1416  * and easier to debug
1417  */
1418 void SetFocus (tmp_win, time)
1419     TwmWindow *tmp_win;
1420     Time        time;
1421 {
1422     Window w = (tmp_win ? tmp_win->w : PointerRoot);
1423
1424 #ifdef TRACE
1425     if (tmp_win) {
1426         printf ("Focusing on window \"%s\"\n", tmp_win->full_name);
1427     } else {
1428         printf ("Unfocusing; Scr->Focus was \"%s\"\n",
1429                 Scr->Focus ? Scr->Focus->full_name : "(nil)");
1430     }
1431 #endif
1432
1433     XSetInputFocus (dpy, w, RevertToPointerRoot, time);
1434 }
1435
1436
1437 #ifdef NEED_PUTENV_F
1438 /*
1439  * define our own putenv() if the system doesn't have one.
1440  * putenv(s): place s (a string of the form "NAME=value") in
1441  * the environment; replacing any existing NAME.  s is placed in
1442  * environment, so if you change s, the environment changes (like
1443  * putenv on a sun).  Binding removed if you putenv something else
1444  * called NAME.
1445  */
1446 int
1447 putenv(s)
1448 /* djhjr - 4/22/98
1449 char *s;
1450 */
1451 const char *s;
1452 {
1453     char *v;
1454     int varlen, idx;
1455     extern char **environ;
1456     char **newenv;
1457     static int virgin = 1; /* true while "environ" is a virgin */
1458
1459     v = index(s, '=');
1460     if(v == 0)
1461         return 0; /* punt if it's not of the right form */
1462     varlen = (v + 1) - s;
1463
1464     for (idx = 0; environ[idx] != 0; idx++) {
1465         if (strncmp(environ[idx], s, varlen) == 0) {
1466             if(v[1] != 0) { /* true if there's a value */
1467                 environ[idx] = (char *)s;
1468                 return 0;
1469             } else {
1470                 do {
1471                     environ[idx] = environ[idx+1];
1472                 } while(environ[++idx] != 0);
1473                 return 0;
1474             }
1475         }
1476     }
1477
1478     /* add to environment (unless no value; then just return) */
1479     if(v[1] == 0)
1480         return 0;
1481     if(virgin) {
1482         register i;
1483
1484         newenv = (char **) malloc((unsigned) ((idx + 2) * sizeof(char*)));
1485         if(newenv == 0)
1486             return -1;
1487         for(i = idx-1; i >= 0; --i)
1488             newenv[i] = environ[i];
1489         virgin = 0;     /* you're not a virgin anymore, sweety */
1490     } else {
1491         newenv = (char **) realloc((char *) environ,
1492                                    (unsigned) ((idx + 2) * sizeof(char*)));
1493         if (newenv == 0)
1494             return -1;
1495     }
1496
1497     environ = newenv;
1498     environ[idx] = (char *)s;
1499     environ[idx+1] = 0;
1500
1501     return 0;
1502 }
1503 #endif /* NEED_PUTENV_F */
1504
1505
1506 /* Returns a blank cursor */
1507 Cursor NoCursor()
1508 {
1509         static Cursor blank = (Cursor) NULL;
1510         Pixmap nopixmap;
1511         XColor nocolor;
1512
1513         if (!blank) {
1514                 nopixmap = XCreatePixmap(dpy, Scr->Root, 1, 1, 1);
1515                 nocolor.red = nocolor.blue = nocolor.green = 0;
1516                 blank = XCreatePixmapCursor(dpy, nopixmap, nopixmap, &nocolor, &nocolor, 1, 1);
1517         }
1518         return(blank);
1519 }
1520
1521 /* djhjr - 10/30/02 */
1522 static void DrawDotImage(d, x, y, w, h, pad, cp, state)
1523 Drawable d;
1524 int x, y, w, h, pad;
1525 ColorPair cp;
1526 int state;
1527 {
1528     XPoint points[5];
1529     int wb, hb, ws, hs, lw;
1530
1531     lw = (w > h) ? h / 16 : w / 16;
1532     if (lw == 1) lw = 0;
1533     XSetForeground(dpy, rootGC, cp.fore);
1534     XSetLineAttributes(dpy, rootGC, lw, LineSolid, CapButt, JoinMiter);
1535
1536     ws = x + (w / 2) - 2;
1537     hs = y + (h / 2) - 2;
1538     wb = ws + 4;
1539     hb = hs + 4;
1540     
1541     points[0].x = points[3].x = points[4].x = ws;
1542     points[0].y = points[1].y = points[4].y = hs;
1543     points[1].x = points[2].x = wb;
1544     points[2].y = points[3].y = hb;
1545     XDrawLines(dpy, d, rootGC, points, 5, CoordModeOrigin);
1546 }
1547
1548 /* djhjr - 10/30/02 */
1549 static void DrawResizeImage(d, x, y, w, h, pad, cp, state)
1550 Drawable d;
1551 int x, y, w, h, pad;
1552 ColorPair cp;
1553 int state;
1554 {
1555     XPoint points[3];
1556     int wb, hb, ws, hs, lw;
1557
1558     lw = (w > h) ? h / 16 : w / 16;
1559     if (lw == 1) lw = 0;
1560     XSetForeground(dpy, rootGC, cp.fore);
1561     XSetLineAttributes(dpy, rootGC, lw, LineSolid, CapButt, JoinMiter);
1562
1563     y--;
1564     wb = w / 4; /* bigger width */
1565     hb = h / 4; /* bigger width */
1566     ws = w / 2; /* smaller width */
1567     hs = h / 2; /* smaller width */
1568
1569     points[0].x = x;
1570     points[0].y = points[1].y = y + hb;
1571     points[1].x = points[2].x = x + w - wb - 1;
1572     points[2].y = y + h;
1573     XDrawLines(dpy, d, rootGC, points, 3, CoordModeOrigin);
1574
1575     points[0].x = x;
1576     points[0].y = points[1].y = y + hs;
1577     points[1].x = points[2].x = x + ws;
1578     points[2].y = y + h;
1579     XDrawLines(dpy, d, rootGC, points, 3, CoordModeOrigin);
1580 }
1581
1582 /* djhjr - 10/30/02 */
1583 static void DrawMenuImage(d, x, y, w, h, pad, cp, state)
1584 Drawable d;
1585 int x, y, w, h, pad;
1586 ColorPair cp;
1587 int state;
1588 {
1589     int ih, iw;
1590     int ix, iy;
1591     int mh, mw;
1592     int tw, th;
1593     int lw, lh;
1594     int lx, ly;
1595     int lines, dly;
1596     /*int off;*/
1597     int bw;
1598
1599     if (h < 1) h = 1;
1600     if (w < 1) w = 1;
1601
1602     ix = iy = pad + 1;
1603     ih = h - iy * 2;
1604     iw = w - ix * 2;
1605     /*off = ih / 8;*/
1606     mh = ih - ih / 8/*off*/;
1607     mw = iw - iw / 8/*off*/;
1608     bw = mh / 16;
1609     if (bw == 0 && mw > 2) bw = 1;
1610     tw = mw - bw * 2;
1611     th = mh - bw * 2;
1612     ix += x;
1613     iy += y;
1614     XSetForeground(dpy, rootGC, cp.fore);
1615     XFillRectangle(dpy, d, rootGC, ix, iy, mw, mh);
1616     XFillRectangle(dpy, d, rootGC, ix + iw - mw, iy + ih - mh, mw, mh);
1617     XSetForeground(dpy, rootGC, cp.back);
1618     XFillRectangle(dpy, d, rootGC, ix + bw, iy + bw, tw, th);
1619
1620     lw = tw / 2;
1621     if ((tw & 1) ^ (lw & 1)) lw++;
1622     lx = ix + bw + (tw - lw) / 2;
1623     lh = th / 2 - bw;
1624     if ((lh & 1) ^ ((th - bw) & 1)) lh++;
1625     ly = iy + bw + (th - bw - lh) / 2;
1626     lines = 3;
1627     if ((lh & 1) && lh < 6) lines--;
1628     dly = lh / (lines - 1);
1629     XSetForeground(dpy, rootGC, cp.fore);
1630     while (lines--)
1631     {
1632         XFillRectangle(dpy, d, rootGC, lx, ly, lw, bw);
1633         ly += dly;
1634     }
1635 }
1636
1637 /* djhjr - 10/30/02 */
1638 static void DrawXLogoImage(d, x, y, w, h, pad, cp, state)
1639 Drawable d;
1640 int x, y, w, h, pad;
1641 ColorPair cp;
1642 int state;
1643 {
1644     GC gcBack;
1645     XGCValues gcvalues;
1646     int lw;
1647
1648     gcBack = XCreateGC(dpy, Scr->Root, 0, &gcvalues);
1649     gcvalues.background = cp.back;
1650     gcvalues.foreground = cp.fore;
1651     XChangeGC(dpy, gcBack, GCForeground | GCBackground, &gcvalues);
1652
1653     lw = (w > h) ? h / 16 : w / 16;
1654     if (lw < 3) lw = 3;
1655     XSetLineAttributes(dpy, gcBack, lw, LineSolid, CapButt, JoinMiter);
1656
1657     /*
1658      * Draw the logo large so that it gets as dense as possible,
1659      * then blank out the edges so that they look crisp.
1660      */
1661
1662     x += pad;
1663     y += pad;
1664     w -= pad * 2;
1665     h -= pad * 2;
1666     XSetForeground(dpy, rootGC, cp.fore);
1667     XSetForeground(dpy, gcBack, cp.back);
1668     XmuDrawLogo(dpy, d, rootGC, gcBack, x - 1, y - 1, w + 2, h + 2);
1669     XDrawRectangle(dpy, d, gcBack, x - 1, y - 1, w + 1, h + 1);
1670
1671     XFreeGC(dpy, gcBack);
1672 }
1673
1674 /* djhjr - 10/30/02 */
1675 static void DrawQuestionImage(d, x, y, w, h, pad, cp, state)
1676 Drawable d;
1677 int x, y, w, h, pad;
1678 ColorPair cp;
1679 int state;
1680 {
1681     Pixmap p;
1682
1683     p = XCreateBitmapFromData(dpy, Scr->Root, questionmark_bits,
1684                               questionmark_width, questionmark_height);
1685
1686     XSetForeground(dpy, rootGC, cp.fore);
1687     XCopyPlane(dpy, p, d, rootGC, 0, 0,
1688                questionmark_width, questionmark_height,
1689                x + (w - questionmark_width) / 2,
1690                y + (h - questionmark_height) / 2,
1691                (unsigned long)1);
1692
1693     XFreePixmap(dpy, p);
1694 }
1695
1696 /* djhjr - 10/30/02 */
1697 static void DrawRArrowImage(d, x, y, w, h, pad, cp, state)
1698 Drawable d;
1699 int x, y, w, h, pad;
1700 ColorPair cp;
1701 int state;
1702 {
1703     XPoint points[4];
1704     int lw, mw, mh;
1705
1706     if (!(h & 1)) h--;
1707     if (h < 1) h = 1;
1708
1709     lw = (w > h) ? h / 16 : w / 16;
1710     if (lw == 1) lw = 0;
1711     XSetForeground(dpy, rootGC, cp.fore);
1712     XSetLineAttributes(dpy, rootGC, lw, LineSolid, CapButt, JoinMiter);
1713
1714     mw = w / 3;
1715     mh = h / 3;
1716     points[0].x = w - mw;
1717     points[0].y = h / 2;
1718     points[1].x = mw - 1;
1719     points[1].y = mh - 1;
1720     points[2].x = mw - 1;
1721     points[2].y = h - mh;
1722     points[3] = points[0];
1723     XDrawLines(dpy, d, rootGC, points, 4, CoordModeOrigin);
1724 }
1725
1726 /* djhjr - 10/30/02 */
1727 static void DrawDArrowImage(d, x, y, w, h, pad, cp, state)
1728 Drawable d;
1729 int x, y, w, h, pad;
1730 ColorPair cp;
1731 int state;
1732 {
1733     XPoint points[4];
1734     int lw, mw, mh;
1735
1736     if (!(h & 1)) h--;
1737     if (h < 1) h = 1;
1738
1739     lw = (w > h) ? h / 16 : w / 16;
1740     if (lw == 1) lw = 0;
1741     XSetForeground(dpy, rootGC, cp.fore);
1742     XSetLineAttributes(dpy, rootGC, lw, LineSolid, CapButt, JoinMiter);
1743
1744     mw = h / 3;
1745     mh = h / 3;
1746     points[0].x = w / 2;
1747     points[0].y = h - mh;
1748     points[1].x = w - mw;
1749     points[1].y = mh - 1;
1750     points[2].x = mw - 1;
1751     points[2].y = mh - 1;
1752     points[3] = points[0];
1753     XDrawLines(dpy, d, rootGC, points, 4, CoordModeOrigin);
1754 }
1755
1756 /* djhjr - 4/19/96 */
1757 /* added d, x, y, w, h, state - djhjr - 10/29/02 */
1758 static void Draw3DDotImage(d, x, y, w, h, pad, cp, state)
1759 Drawable d;
1760 int x, y, w, h, pad;
1761 ColorPair cp;
1762 int state;
1763 {
1764     Draw3DBorder(d, x + (w / 2) - 2, y + (h / 2) - 2, 5, 5,
1765                  Scr->ShallowReliefWindowButton, cp, state, True, False);
1766 }
1767
1768 /* djhjr - 4/19/96 */
1769 /* added d, x, y, w, h, state - djhjr - 10/29/02 */
1770 static void Draw3DBarImage(d, x, y, w, h, pad, cp, state)
1771 Drawable d;
1772 int x, y, w, h, pad;
1773 ColorPair cp;
1774 int state;
1775 {
1776         /* was 'Scr->TitleBevelWidth' - djhjr - 8/11/98 */
1777         Draw3DBorder (d, x + pad + 1, y + (h - 5) / 2,
1778                 w - pad * 2 - 2, 5,
1779                 Scr->ShallowReliefWindowButton, cp, state, True, False);
1780 }
1781
1782 /* djhjr - 4/19/96 */
1783 /* added d, x, y, w, h, state - djhjr - 10/29/02 */
1784 static void Draw3DMenuImage(d, x, y, w, h, pad, cp, state)
1785 Drawable d;
1786 int x, y, w, h, pad;
1787 ColorPair cp;
1788 int state;
1789 {
1790         int i, lines, width, height;
1791
1792         height = Scr->ShallowReliefWindowButton * 2;
1793
1794         /* count the menu lines */
1795         lines = (h - pad * 2 - 2) / height;
1796         /* center 'em */
1797         y += (h - lines * height) / 2;
1798         if (!(y & 1)) y += 1;
1799         /* now draw 'em */
1800         x += pad + 1;
1801         lines = y + lines * height;
1802         width = w - pad * 2 - 2;
1803         for (i = y; i < lines; i += height)
1804                 Draw3DBorder(d, x, i, width, height,
1805                              Scr->ShallowReliefWindowButton,
1806                              cp, state, True, False);
1807 }
1808
1809 /* djhjr - 4/19/96 */
1810 /* added d, x, y, w, h, state - djhjr - 10/29/02 */
1811 static void Draw3DResizeImage(d, x, y, w, h, pad, cp, state)
1812 Drawable d;
1813 int x, y, w, h, pad;
1814 ColorPair cp;
1815 int state;
1816 {
1817     int   i, j;
1818
1819     /* djhjr - 4/29/98 */
1820     /* was 'Scr->TitleBevelWidth' - djhjr - 8/11/98 */
1821     i = w - Scr->ButtonBevelWidth * 2;
1822
1823     /*
1824      * Extend the left and bottom "off-window" by the
1825      * line width for "thick" boxes on "thin" buttons.
1826      */
1827
1828     /* was 'Scr->TitleBevelWidth' - djhjr - 8/11/98 */
1829     j = Scr->ButtonBevelWidth + (i / 4);
1830     Draw3DBorder(d,
1831                 x + -Scr->ShallowReliefWindowButton, y + j - 1,
1832                 x + w - j + 1 + Scr->ShallowReliefWindowButton,
1833                 y + h - j + 1 + Scr->ShallowReliefWindowButton,
1834                 Scr->ShallowReliefWindowButton, cp, state, True, False);
1835
1836     j = Scr->ButtonBevelWidth + (i / 2);
1837     Draw3DBorder(d,
1838                 x + -Scr->ShallowReliefWindowButton, y + j,
1839                 x + w - j + Scr->ShallowReliefWindowButton,
1840                 y + h - j + Scr->ShallowReliefWindowButton,
1841                 Scr->ShallowReliefWindowButton, cp, state, True, False);
1842 }
1843
1844 /* djhjr - 4/19/96 */
1845 /* added d, x, y, w, h, state - djhjr - 10/29/02 */
1846 static void Draw3DZoomImage(d, x, y, w, h, pad, cp, state)
1847 Drawable d;
1848 int x, y, w, h, pad;
1849 ColorPair cp;
1850 int state;
1851 {
1852         /* was 'Scr->TitleBevelWidth' - djhjr - 8/11/98 */
1853         Draw3DBorder (d,
1854                 x + pad + 1, y + pad + 1,
1855                 w - 2 * pad - 2,
1856                 h - 2 * pad - 2,
1857                 Scr->ShallowReliefWindowButton, cp, state, True, False);
1858 }
1859
1860 /* djhjr - 6/4/00 */
1861 /* added d, x, y, w, h, state - djhjr - 10/29/02 */
1862 static void Draw3DRArrowImage(d, x, y, w, h, pad, cp, state)
1863 Drawable d;
1864 int x, y, w, h, pad;
1865 ColorPair cp;
1866 int state;
1867 {
1868     int i, mw, mh;
1869
1870         mw = w / 3;
1871         mh = h / 3;
1872
1873         if (Scr->Monochrome != COLOR)
1874         {
1875                 /* draw highlights */
1876                 setBorderGC(1, Scr->GreyGC, cp, state, False);
1877                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
1878                 {
1879                         XDrawLine(dpy, d, Scr->GreyGC,
1880                                 x + w - mw - i, y + h / 2,
1881                                 x + mw - 1 + i, y + mh - 1 + i);
1882                         XDrawLine (dpy, d, Scr->GreyGC,
1883                                 x + mw - 1 + i, y + mh - 1 + i,
1884                                 x + mw - 1 + i, y + h - mh - i);
1885                 }
1886
1887                 /* draw shadows */
1888                 setBorderGC(2, Scr->GreyGC, cp, state, False);
1889                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
1890                         XDrawLine (dpy, d, Scr->GreyGC,
1891                                 x + mw - 1 + i, y + h - mh - i,
1892                                 x + w - mw - i, y + h / 2);
1893     }
1894         else if (Scr->BeNiceToColormap)
1895         {
1896                 int dashoffset = 0;
1897
1898                 setBorderGC(3, Scr->ShadGC, cp, state, False);
1899             
1900                 /* draw highlights */
1901                 XSetForeground (dpy, Scr->ShadGC, Scr->White);
1902                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
1903                 {
1904                         XDrawLine(dpy, d, Scr->ShadGC,
1905                                 x + w - mw - i, y + h / 2,
1906                                 x + mw - 1 + i, y + mh - 1 + i);
1907                         XDrawLine (dpy, d, Scr->ShadGC,
1908                                 x + mw - 1 + i, y + mh - 1 + i,
1909                                 x + mw - 1 + i, y + h - mh - i);
1910                 }
1911
1912                 /* draw shadows */
1913                 XSetForeground (dpy, Scr->ShadGC, Scr->Black);
1914                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
1915                 {
1916                         XDrawLine (dpy, d, Scr->ShadGC,
1917                                 x + mw - 1 + i, y + h - mh - i + dashoffset,
1918                                 x + w - mw - i, y + h / 2 + dashoffset);
1919                         dashoffset = 1 - dashoffset;
1920                 }
1921         }
1922         else
1923         {
1924                 /* draw highlights */
1925                 if (state)
1926                 { FB (cp.shadc, cp.shadd); }
1927                 else
1928                 { FB (cp.shadd, cp.shadc); }
1929                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
1930                 {
1931                         XDrawLine(dpy, d, Scr->NormalGC,
1932                                 x + w - mw - i, y + h / 2,
1933                                 x + mw - 1 + i, y + mh - 1 + i);
1934                         XDrawLine (dpy, d, Scr->NormalGC,
1935                                 x + mw - 1 + i, y + mh - 1 + i,
1936                                 x + mw - 1 + i, y + h - mh - i);
1937                 }
1938
1939                 /* draw shadows */
1940                 if (state)
1941                 { FB (cp.shadd, cp.shadc); }
1942                 else
1943                 { FB (cp.shadc, cp.shadd); }
1944                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
1945                         XDrawLine (dpy, d, Scr->NormalGC,
1946                                 x + mw - 1 + i, y + h - mw - i,
1947                                 x + w - mw - i, y + h / 2);
1948         }
1949 }
1950
1951 /* djhjr - 6/4/00 */
1952 /* added d, x, y, w, h, state - djhjr - 10/29/02 */
1953 static void Draw3DDArrowImage(d, x, y, w, h, pad, cp, state)
1954 Drawable d;
1955 int x, y, w, h, pad;
1956 ColorPair cp;
1957 int state;
1958 {
1959     int i, mw, mh;
1960
1961         mw = w / 3;
1962         mh = h / 3;
1963
1964         if (Scr->Monochrome != COLOR)
1965         {
1966                 /* draw highlights */
1967                 setBorderGC(1, Scr->GreyGC, cp, state, False);
1968                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
1969                 {
1970                         XDrawLine(dpy, d, Scr->GreyGC,
1971                                 x + w - mw - i, y + mh - 1 + i,
1972                                 x + mw - 1 + i, y + mh - 1 + i);
1973                         XDrawLine (dpy, d, Scr->GreyGC,
1974                                 x + mw - 1 + i, y + mh - 1 + i,
1975                                 x + w / 2, y + mh - 1 - i + h / 2);
1976                 }
1977
1978                 /* draw shadows */
1979                 setBorderGC(2, Scr->GreyGC, cp, state, False);
1980                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
1981                         XDrawLine (dpy, d, Scr->GreyGC,
1982                                 x + w / 2, y + mh - 1 - i + h / 2,
1983                                 x + w - mw - i, y + mh + i);
1984     }
1985         else if (Scr->BeNiceToColormap)
1986         {
1987                 int dashoffset = 0;
1988
1989                 setBorderGC(3, Scr->ShadGC, cp, state, False);
1990             
1991                 /* draw highlights */
1992                 XSetForeground (dpy, Scr->ShadGC, Scr->White);
1993                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
1994                 {
1995                         XDrawLine(dpy, d, Scr->ShadGC,
1996                                 x + w - mw - i, y + mh - 1 + i,
1997                                 x + mw - 1 + i, y + mh - 1 + i);
1998                         XDrawLine (dpy, d, Scr->ShadGC,
1999                                 x + mw - 1 + i, y + mh - 1 + i + dashoffset,
2000                                 x + w / 2, y + mh - 1 - i + h / 2 + dashoffset);
2001                         dashoffset = 1 - dashoffset;
2002                 }
2003
2004                 /* draw shadows */
2005                 XSetForeground (dpy, Scr->ShadGC, Scr->Black);
2006                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
2007                         XDrawLine (dpy, d, Scr->ShadGC,
2008                                 x + w / 2, y + mh - 1 - i + h / 2,
2009                                 x + w - mw - i, y + mh + i);
2010         }
2011         else
2012         {
2013                 /* draw highlights */
2014                 if (state)
2015                 { FB (cp.shadc, cp.shadd); }
2016                 else
2017                 { FB (cp.shadd, cp.shadc); }
2018                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
2019                 {
2020                         XDrawLine(dpy, d, Scr->NormalGC,
2021                                 x + w - mw - i, y + mh - 1 + i,
2022                                 x + mw - 1 + i, y + mh - 1 + i);
2023                         XDrawLine (dpy, d, Scr->NormalGC,
2024                                 x + mw - 1 + i, y + mh - 1 + i,
2025                                 x + w / 2, y + mh - 1 - i + h / 2);
2026                 }
2027
2028                 /* draw shadows */
2029                 if (state)
2030                 { FB (cp.shadd, cp.shadc); }
2031                 else
2032                 { FB (cp.shadc, cp.shadd); }
2033                 for (i = 0; i < Scr->ShallowReliefWindowButton; i++)
2034                         XDrawLine (dpy, d, Scr->NormalGC,
2035                                 x + w / 2, y + mh - 1 - i + h / 2,
2036                                 x + w - mw - i, y + mh + i);
2037         }
2038 }
2039
2040 /* djhjr - 10/25/02 */
2041 static void Draw3DBoxHighlight(d, x, y, w, h, pad, cp, state)
2042 Drawable d;
2043 int x, y, w, h, pad;
2044 ColorPair cp;
2045 int state;
2046 {
2047         Draw3DBorder(d, x, y, w, h,
2048                      Scr->ShallowReliefWindowButton, cp,
2049                      state, True, False);
2050 }
2051
2052 /* djhjr - 10/25/02 */
2053 static void Draw3DLinesHighlight(d, x, y, w, h, pad, cp, state)
2054 Drawable d;
2055 int x, y, w, h, pad;
2056 ColorPair cp;
2057 int state;
2058 {
2059         int p;
2060         
2061         p = (Scr->ShallowReliefWindowButton & 1) ? 3 : 2;
2062         p = (h - Scr->ShallowReliefWindowButton * p - 2) / 2;
2063
2064         y += h / 2 - 1;
2065         y -= (Scr->ShallowReliefWindowButton & 1) ? 0 : 1;
2066         y += (state == on) ? 0 : 1;
2067
2068         h = Scr->ShallowReliefWindowButton * 2;
2069
2070         Draw3DBorder(d, x, y - p, w, h,
2071                      Scr->ShallowReliefWindowButton, cp,
2072                      state, False, False);
2073
2074         if ((Scr->ShallowReliefWindowButton & 1))
2075                 Draw3DBorder(d, x, y, w, h,
2076                              Scr->ShallowReliefWindowButton, cp,
2077                              state, False, False);
2078
2079         Draw3DBorder(d, x, y + p, w, h,
2080                      Scr->ShallowReliefWindowButton, cp,
2081                      state, False, False);
2082 }
2083
2084 /* ick - djhjr - 10/30/02 */
2085 static void DrawBackground(d, x, y, w, h, cp, use_rootGC)
2086 Drawable d;
2087 int x, y, w, h;
2088 ColorPair cp;
2089 int use_rootGC;
2090 {
2091     XGCValues gcvalues;
2092
2093     if (use_rootGC)
2094     {
2095         if (rootGC == (GC)0)
2096             rootGC = XCreateGC(dpy, Scr->Root, 0, &gcvalues);
2097
2098         gcvalues.background = cp.back;
2099         gcvalues.foreground = cp.fore;
2100         XChangeGC(dpy, rootGC, GCForeground | GCBackground, &gcvalues);
2101
2102         XSetForeground(dpy, rootGC, cp.back);
2103         XFillRectangle(dpy, d, rootGC, x, y, w, h);
2104     }
2105     else
2106     {
2107         FB(cp.back, cp.fore);
2108         XFillRectangle(dpy, d, Scr->NormalGC, x, y, w, h);
2109     }
2110 }
2111
2112 /* djhjr - 10/25/02 */
2113 static void DrawTitleHighlight(t, state)
2114 TwmWindow *t;
2115 int state;
2116 {
2117         static const struct {
2118                 char *name;
2119                 void (*proc)();
2120                 Bool use_rootGC;
2121                 int state;
2122         } pmtab[] = {
2123                 /* djhjr - 10/30/02 */
2124                 { TBPM_DOT,             DrawDotImage,           True, off  },
2125                 { TBPM_ICONIFY,         DrawDotImage,           True, off  },
2126                 { TBPM_RESIZE,          DrawResizeImage,        True, off  },
2127                 { TBPM_MENU,            DrawMenuImage,          True, off  },
2128                 { TBPM_XLOGO,           DrawXLogoImage,         True, off  },
2129                 { TBPM_DELETE,          DrawXLogoImage,         True, off  },
2130                 { TBPM_QUESTION,        DrawQuestionImage,      True, off  },
2131
2132                 { TBPM_3DDOT,           Draw3DDotImage,         False, off },
2133                 { TBPM_3DRESIZE,        Draw3DResizeImage,      False, off },
2134                 { TBPM_3DMENU,          Draw3DMenuImage,        False, off },
2135                 { TBPM_3DZOOM,          Draw3DZoomImage,        False, off },
2136                 { TBPM_3DBAR,           Draw3DBarImage,         False, off },
2137
2138                 /* djhjr - 10/30/02 */
2139                 { TBPM_3DBOX,           Draw3DBoxHighlight,     False, off },
2140                 { TBPM_3DLINES,         Draw3DLinesHighlight,   False, off },
2141
2142                 { TBPM_3DRAISEDBOX,     Draw3DBoxHighlight,     False, off },
2143                 { TBPM_3DSUNKENBOX,     Draw3DBoxHighlight,     False, on  },
2144                 { TBPM_3DRAISEDLINES,   Draw3DLinesHighlight,   False, off },
2145                 { TBPM_3DSUNKENLINES,   Draw3DLinesHighlight,   False, on  },
2146         };
2147
2148         XGCValues gcvalues;
2149         ColorPair cp;
2150         register int i;
2151         int h, w;
2152         
2153         cp = t->title;
2154         w = ComputeHighlightWindowWidth(t);
2155         h = Scr->TitleHeight - 2 * Scr->FramePadding - 2;
2156                 
2157         for (i = 0; i < sizeof(pmtab) / sizeof(pmtab[0]); i++)
2158         {
2159                 if (XmuCompareISOLatin1(pmtab[i].name, Scr->hiliteName) == 0)
2160                 {
2161                         if (state == off)
2162                         {
2163                                 DrawBackground(t->title_w,
2164                                                t->highlightx,
2165                                                Scr->FramePadding + 1,
2166                                                w, h, cp,
2167                                                pmtab[i].use_rootGC | (Scr->Monochrome != COLOR));
2168                         }
2169                         else
2170                         {
2171                                 /* ick - djhjr - 10/30/02 */
2172                                 if (pmtab[i].use_rootGC)
2173                                 {
2174                                         if (rootGC == (GC)0)
2175                                                 rootGC = XCreateGC(dpy,
2176                                                                    Scr->Root,
2177                                                                    0,
2178                                                                    &gcvalues);
2179
2180                                         gcvalues.background = cp.back;
2181                                         gcvalues.foreground = cp.fore;
2182                                         XChangeGC(dpy, rootGC,
2183                                                   GCForeground | GCBackground,
2184                                                   &gcvalues);
2185                                 }
2186
2187                                 (*pmtab[i].proc)(t->title_w,
2188                                                  t->highlightx,
2189                                                  Scr->FramePadding + 1,
2190                                                  w, h, 0, cp, pmtab[i].state);
2191                         }
2192
2193                         break;
2194                 }
2195         }
2196 }
2197
2198 /* djhjr - 1/13/98 */
2199 void setBorderGC(type, gc, cp, state, forcebw)
2200 int                     type, state, forcebw;
2201 GC                      gc;
2202 ColorPair       cp;
2203 {
2204         XGCValues               gcv;
2205         unsigned long   gcm;
2206
2207         switch (type)
2208         {
2209                 case 0: /* Monochrome main */
2210                         gcm = GCFillStyle;
2211                         gcv.fill_style = FillOpaqueStippled;
2212                         break;
2213                 case 1: /* Monochrome highlight */
2214                         gcm  = 0;
2215                         gcm |= GCLineStyle;             
2216                         gcv.line_style = (state == on) ? LineSolid : LineDoubleDash;
2217                         gcm |= GCFillStyle;
2218                         gcv.fill_style = FillSolid;
2219                         break;
2220                 case 2: /* Monochrome shadow */
2221                         gcm  = 0;
2222                         gcm |= GCLineStyle;             
2223                         gcv.line_style = (state == on) ? LineDoubleDash : LineSolid;
2224                         gcm |= GCFillStyle;
2225                         gcv.fill_style = FillSolid;
2226                         break;
2227                 case 3: /* BeNiceToColormap */
2228                         gcm  = 0;
2229                         gcm |= GCLineStyle;             
2230                         gcv.line_style = (forcebw) ? LineSolid : LineDoubleDash;
2231                         gcm |= GCBackground;
2232                         gcv.background = cp.back;
2233                         break;
2234                 default:
2235                         return;
2236         }
2237
2238         XChangeGC (dpy, gc, gcm, &gcv);
2239 }
2240
2241 /* djhjr - 4/19/96 */
2242 void Draw3DBorder (w, x, y, width, height, bw, cp, state, fill, forcebw)
2243 Drawable                w;
2244 int                     x, y, width, height, bw;
2245 ColorPair       cp;
2246 int                     state, fill, forcebw;
2247 {
2248         int                             i;
2249
2250         if (width < 1 || height < 1) return;
2251
2252         if (Scr->Monochrome != COLOR)
2253         {
2254                 /* set main color */
2255                 if (fill)
2256                 {
2257                         setBorderGC(0, Scr->GreyGC, cp, state, forcebw);
2258                         XFillRectangle (dpy, w, Scr->GreyGC, x, y, width, height);
2259                 }
2260
2261                 /* draw highlights */
2262                 setBorderGC(1, Scr->GreyGC, cp, state, forcebw);
2263                 for (i = 0; i < bw; i++)
2264                 {
2265                         XDrawLine (dpy, w, Scr->GreyGC, x, y + i,
2266                                 x + width - i - 1, y + i);
2267                         XDrawLine (dpy, w, Scr->GreyGC, x + i, y,
2268                                 x + i, y + height - i - 1);
2269                 }
2270
2271                 /* draw shadows */
2272                 setBorderGC(2, Scr->GreyGC, cp, state, forcebw);
2273                 for (i = 0; i < bw; i++)
2274                 {
2275                         XDrawLine (dpy, w, Scr->GreyGC, x + width - i - 1, y + i,
2276                                 x + width - i - 1, y + height - 1);
2277                         XDrawLine (dpy, w, Scr->GreyGC, x + i, y + height - i - 1,
2278                                 x + width - 1, y + height - i - 1);
2279                 }
2280
2281                 return;
2282     }
2283
2284         /* set main color */
2285         if (fill)
2286         {
2287                 FB (cp.back, cp.fore);
2288                 XFillRectangle (dpy, w, Scr->NormalGC, x, y, width, height);
2289         }
2290
2291         if (Scr->BeNiceToColormap)
2292         {
2293                 setBorderGC(3, Scr->ShadGC, cp, state, forcebw);
2294             
2295                 /* draw highlights */
2296                 if (state == on)
2297                         XSetForeground (dpy, Scr->ShadGC, Scr->Black);
2298                 else
2299                         XSetForeground (dpy, Scr->ShadGC, Scr->White);
2300                 for (i = 0; i < bw; i++)
2301                 {
2302                         XDrawLine (dpy, w, Scr->ShadGC,
2303                                 x + i, y + borderdashoffset,
2304                                 x + i, y + height - i - 1);
2305                         XDrawLine (dpy, w, Scr->ShadGC,
2306                                 x + borderdashoffset, y + i,
2307                                 x + width - i - 1, y + i);
2308                         borderdashoffset = 1 - borderdashoffset;
2309                 }
2310
2311                 /* draw shadows */
2312                 if (state == on)
2313                         XSetForeground (dpy, Scr->ShadGC, Scr->White);
2314                 else
2315                         XSetForeground (dpy, Scr->ShadGC, Scr->Black);
2316                 for (i = 0; i < bw; i++)
2317                 {
2318                         XDrawLine (dpy, w, Scr->ShadGC, x + i, y + height - i - 1,
2319                                 x + width - 1, y + height - i - 1);
2320                         XDrawLine (dpy, w, Scr->ShadGC, x + width - i - 1, y + i,
2321                                 x + width - i - 1, y + height - 1);
2322                 }
2323
2324                 return;
2325         }
2326
2327         /* draw highlights */
2328         if (state == on)
2329                 { FB (cp.shadd, cp.shadc); }
2330         else
2331                 { FB (cp.shadc, cp.shadd); }
2332         for (i = 0; i < bw; i++)
2333         {
2334                 XDrawLine (dpy, w, Scr->NormalGC, x, y + i,
2335                         x + width - i - 1, y + i);
2336                 XDrawLine (dpy, w, Scr->NormalGC, x + i, y,
2337                         x + i, y + height - i - 1);
2338         }
2339
2340         /* draw shadows */
2341         if (state == on)
2342                 { FB (cp.shadc, cp.shadd); }
2343         else
2344                 { FB (cp.shadd, cp.shadc); }
2345         for (i = 0; i < bw; i++)
2346         {
2347                 XDrawLine (dpy, w, Scr->NormalGC, x + width - i - 1, y + i,
2348                         x + width - i - 1, y + height - 1);
2349                 XDrawLine (dpy, w, Scr->NormalGC, x + i, y + height - i - 1,
2350                         x + width - 1, y + height - i - 1);
2351         }
2352 }
2353
2354 #ifdef USE_ORIGINAL_CORNERS
2355 /* djhjr - 4/19/96 */
2356 void Draw3DCorner (w, x, y, width, height, thick, bw, cp, type)
2357 Window          w;
2358 int                     x, y, width, height, thick, bw;
2359 ColorPair       cp;
2360 int                     type;
2361 {
2362         Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False);
2363
2364         switch (type)
2365         {
2366                 /* upper left */
2367                 case 0 :
2368                         Draw3DBorder (w, x + thick - bw, y + thick - bw,
2369                                 width - thick + 2 * bw, height - thick + 2 * bw,
2370                                 bw, cp, on, True, False);
2371                         break;
2372                 /* upper right */
2373                 case 1 :
2374                         Draw3DBorder (w, x - bw, y + thick - bw,
2375                                 width - thick + 2 * bw, height - thick + 2 * bw,
2376                                 bw, cp, on, True, False);
2377                         break;
2378                 /* lower right */
2379                 case 2 :
2380                         Draw3DBorder (w, x - bw, y - bw,
2381                                 width - thick + 2 * bw, height - thick + 2 * bw,
2382                                 bw, cp, on, True, False);
2383                         break;
2384                 /* lower left */
2385                 case 3 :
2386                         Draw3DBorder (w, x + thick - bw, y - bw,
2387                                 width - thick + 2 * bw, height - thick + 2 * bw,
2388                                 bw, cp, on, True, False);
2389                         break;
2390         }
2391 }
2392 #else /* USE_ORIGINAL_CORNERS */
2393 /* djhjr - 1/14/98 */
2394 GC setBevelGC(type, state, cp)
2395 int                     type, state;
2396 ColorPair       cp;
2397 {
2398         GC              gc;
2399
2400         if (Scr->Monochrome != COLOR)
2401         {
2402                 gc = Scr->GreyGC;
2403                 setBorderGC(type, gc, cp, state, False);
2404         }
2405         else if (Scr->BeNiceToColormap)
2406         {
2407                 gc = Scr->ShadGC;
2408                 setBorderGC(3, gc, cp, state, False);
2409                 if (state == on)
2410                         XSetForeground (dpy, gc, Scr->Black);
2411                 else
2412                         XSetForeground (dpy, gc, Scr->White);
2413         }
2414         else
2415         {
2416                 gc = Scr->NormalGC;
2417                 if (state == on)
2418                         { FB (cp.shadc, cp.shadd); }
2419                 else
2420                         { FB (cp.shadd, cp.shadc); }
2421         }
2422
2423         return (gc);
2424 }
2425
2426 /* djhjr - 1/12/98 */
2427 void Draw3DBevel (w, x, y, bw, cp, state, type)
2428 Drawable                w;
2429 int                     x, y, bw;
2430 ColorPair       cp;
2431 int                     state, type;
2432 {
2433         int             i;
2434         GC              gc;
2435
2436         switch (type)
2437         {
2438                 /* vertical */
2439                 case 1 :
2440                 case 11 :
2441                         gc = setBevelGC(1, state, cp);
2442                         for (i = 0; i < Scr->BorderBevelWidth; i++)
2443                                 XDrawLine (dpy, w, gc, x - i - 1, y + i,
2444                                         x - i - 1, y + bw - 2 * i + i);
2445                         if (type == 11) break;
2446                 case 111 :
2447                         gc = setBevelGC(2, !state, cp);
2448                         for (i = 0; i < Scr->BorderBevelWidth; i++)
2449                                 XDrawLine (dpy, w, gc, x + i, y + i - 1,
2450                                         x + i, y + bw - 2 * i + i - 1);
2451                         break;
2452                 /* horizontal */
2453                 case 2 :
2454                 case 22 :
2455                         gc = setBevelGC(1, state, cp);
2456                         for (i = 0; i < Scr->BorderBevelWidth; i++)
2457                                 XDrawLine (dpy, w, gc, x + i, y - i - 1,
2458                                         x + bw - 2 * i + i, y - i - 1);
2459                         if (type == 22) break;
2460                 case 222 :
2461                         gc = setBevelGC(2, !state, cp);
2462                         for (i = 0; i < Scr->BorderBevelWidth; i++)
2463                                 XDrawLine (dpy, w, gc, x + i - 1, y + i,
2464                                         x + bw - 2 * i + i - 1, y + i);
2465                         break;
2466                 /* ulc to lrc */
2467                 case 3 :
2468                         if (Scr->Monochrome != COLOR)
2469                         {
2470                                 gc = Scr->GreyGC;
2471                                 setBorderGC(0, gc, cp, state, False);
2472                         }
2473                         else
2474                         {
2475                                 gc = Scr->NormalGC;
2476                                 FB (cp.back, cp.fore);
2477                         }
2478                         XFillRectangle (dpy, w, gc, x, y, bw, bw);
2479                         gc = setBevelGC(1, (Scr->BeNiceToColormap) ? state : !state, cp);
2480                         for (i = 0; i < Scr->BorderBevelWidth; i++)
2481                                 XDrawLine (dpy, w, gc, x + i, y,
2482                                         x + i, y + Scr->BorderBevelWidth - 1);
2483                         gc = setBevelGC(2, (Scr->BeNiceToColormap) ? !state : state, cp);
2484                         for (i = 0; i < Scr->BorderBevelWidth; i++)
2485                                 XDrawLine (dpy, w, gc, x, y + bw - i - 1,
2486                                         x + bw - 1, y + bw - i - 1);
2487                         for (i = 0; i < Scr->BorderBevelWidth; i++)
2488                                 XDrawLine (dpy, w, gc, x + bw - i - 1, y,
2489                                         x + bw - i - 1, y + bw - 1);
2490                         break;
2491                 /* urc to llc */
2492                 case 4 :
2493                         if (Scr->Monochrome != COLOR)
2494                         {
2495                                 gc = Scr->GreyGC;
2496                                 setBorderGC(0, gc, cp, state, False);
2497                         }
2498                         else
2499                         {
2500                                 gc = Scr->NormalGC;
2501                                 FB (cp.back, cp.fore);
2502                         }
2503                         XFillRectangle (dpy, w, gc, x, y, bw, bw);
2504                         gc = setBevelGC(1, (Scr->BeNiceToColormap) ? state : !state, cp);
2505                         /* top light */
2506                         for (i = 0; i < Scr->BorderBevelWidth; i++)
2507                                 XDrawLine (dpy, w, gc, x + i, y,
2508                                         x + i, y + bw - i);
2509                         /* bottom light */
2510                         for (i = 0; i < Scr->BorderBevelWidth; i++)
2511                                 XDrawLine (dpy, w, gc, x + bw - 1, y + i,
2512                                         x + bw - i - 1, y + i);
2513                         gc = setBevelGC(2, (Scr->BeNiceToColormap) ? !state : state, cp);
2514                         /* top dark */
2515                         for (i = 0; i < Scr->BorderBevelWidth - 1; i++)
2516                                 XDrawLine (dpy, w, gc, x + bw - Scr->BorderBevelWidth, y + i,
2517                                         x + bw - i - 2, y + i);
2518                         /* bottom dark */
2519                         for (i = 0; i < Scr->BorderBevelWidth; i++)
2520                                 XDrawLine (dpy, w, gc, x + i, y + bw - i - 1,
2521                                         x + bw + 1, y + bw - i - 1);
2522                         break;
2523         }
2524 }
2525
2526 /* djhjr - 10/20/02 */
2527 void Draw3DNoBevel(w, x, y, bw, cp, state, forcebw)
2528 Drawable        w;
2529 int             x, y, bw;
2530 ColorPair       cp;
2531 int             state, forcebw;
2532 {
2533         int             i, upr, lwr;
2534
2535         if (bw < 1) return;
2536
2537         upr = y - 2 * Scr->BorderBevelWidth;
2538         if ((upr & 1)) upr--;
2539         lwr = y + 2 * Scr->BorderBevelWidth;
2540         if ((lwr & 1)) lwr++;
2541
2542         if (Scr->Monochrome != COLOR)
2543         {
2544                 /* set main color */
2545                 setBorderGC(0, Scr->GreyGC, cp, state, forcebw);
2546                 XFillRectangle (dpy, w, Scr->GreyGC,
2547                         x + Scr->BorderBevelWidth, upr,
2548                         (unsigned int)(bw - Scr->BorderBevelWidth * 2),
2549                         (unsigned int)(upr * 2));
2550
2551                 /* draw highlight */
2552                 setBorderGC(1, Scr->GreyGC, cp, state, forcebw);
2553                 for (i = 0; i < Scr->BorderBevelWidth; i++)
2554                         XDrawLine (dpy, w, Scr->GreyGC,
2555                                 x + i, upr, x + i, lwr);
2556                 
2557                 /* draw shadow */
2558                 setBorderGC(2, Scr->GreyGC, cp, state, forcebw);
2559                 for (i = bw - Scr->BorderBevelWidth; i < bw; i++)
2560                         XDrawLine (dpy, w, Scr->GreyGC,
2561                                 x + i, upr, x + i, lwr);
2562
2563                 return;
2564         }
2565
2566         /* set main color */
2567         FB (cp.back, cp.fore);
2568         XFillRectangle (dpy, w, Scr->NormalGC,
2569                 x + Scr->BorderBevelWidth, upr,
2570                 (unsigned int)(bw - Scr->BorderBevelWidth * 2),
2571                 (unsigned int)(upr * 2));
2572
2573         if (Scr->BeNiceToColormap)
2574         {
2575                 int dashoffset;
2576
2577                 setBorderGC(3, Scr->ShadGC, cp, state, forcebw);
2578             
2579                 /* draw highlight */
2580                 if (state == on)
2581                         XSetForeground (dpy, Scr->ShadGC, Scr->Black);
2582                 else
2583                         XSetForeground (dpy, Scr->ShadGC, Scr->White);
2584                 dashoffset = 0;
2585                 for (i = 0; i < Scr->BorderBevelWidth; i++)
2586                 {
2587                         XDrawLine (dpy, w, Scr->ShadGC,
2588                                 x + i, upr + dashoffset, x + i, lwr);
2589                         dashoffset = 1 - dashoffset;
2590                 }
2591
2592                 /* draw shadow */
2593                 if (state == on)
2594                         XSetForeground (dpy, Scr->ShadGC, Scr->White);
2595                 else
2596                         XSetForeground (dpy, Scr->ShadGC, Scr->Black);
2597                 dashoffset = 0;
2598                 for (i = bw - Scr->BorderBevelWidth; i < bw; i++)
2599                 {
2600                         XDrawLine (dpy, w, Scr->ShadGC,
2601                                 x + i, upr + dashoffset, x + i, lwr);
2602                         dashoffset = 1 - dashoffset;
2603                 }
2604
2605                 return;
2606         }
2607
2608         /* draw highlight */
2609         if (state == on)
2610                 { FB (cp.shadc, cp.shadd); }
2611         else
2612                 { FB (cp.shadd, cp.shadc); }
2613         for (i = 0; i < Scr->BorderBevelWidth; i++)
2614                 XDrawLine (dpy, w, Scr->NormalGC,
2615                         x + i, upr, x + i, lwr);
2616
2617         /* draw shadow */
2618         if (state == on)
2619                 { FB (cp.shadd, cp.shadc); }
2620         else
2621                 { FB (cp.shadc, cp.shadd); }
2622         for (i = bw - Scr->BorderBevelWidth; i < bw; i++)
2623                 XDrawLine (dpy, w, Scr->NormalGC,
2624                         x + i, upr, x + i, lwr);
2625 }
2626 #endif /* USE_ORIGINAL_CORNERS */
2627
2628 /* djhjr - 4/19/96 */
2629 static Image *LoadBitmapImage (name, cp)
2630 char  *name;
2631 ColorPair cp;
2632 {
2633     Image       *image;
2634     Pixmap      bm;
2635     int         width, height;
2636     XGCValues   gcvalues;
2637
2638     if (rootGC == (GC) 0) rootGC = XCreateGC (dpy, Scr->Root, 0, &gcvalues);
2639     bm = FindBitmap (name, (unsigned int *) &width, (unsigned int *) &height);
2640     if (bm == None) return (None);
2641
2642     image = (Image*) malloc (sizeof (struct _Image));
2643     image->pixmap = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth);
2644     gcvalues.background = cp.back;
2645     gcvalues.foreground = cp.fore;
2646     XChangeGC   (dpy, rootGC, GCForeground | GCBackground, &gcvalues);
2647     XCopyPlane  (dpy, bm, image->pixmap, rootGC, 0, 0, width, height, 0, 0, (unsigned long) 1);
2648     XFreePixmap (dpy, bm);
2649     image->mask   = None;
2650     image->width  = width;
2651     image->height = height;
2652     image->next   = None;
2653     return (image);
2654 }
2655
2656 /* djhjr - 10/30/02 */
2657 static Image *CreateImagePixmap(name, w, h, depth)
2658 char *name;
2659 int w, h, depth;
2660 {
2661     Image *image;
2662
2663     image = (Image *)malloc(sizeof(struct _Image));
2664     if (!image)
2665     {
2666         fprintf(stderr, "%s: cannot allocate %d bytes for Image \"%s\"\n",
2667                         ProgramName, sizeof(struct _Image), name);
2668         return (None);
2669     }
2670
2671     image->pixmap = XCreatePixmap(dpy, Scr->Root, w, h, depth);
2672     if (image->pixmap == None)
2673     {
2674         fprintf(stderr, "%s: cannot allocate %d bytes for pixmap \"%s\"\n",
2675                         ProgramName, sizeof(image->pixmap), name);
2676         free((void *)image);
2677         return (None);
2678     }
2679
2680     return (image);
2681 }
2682
2683 /* djhjr - 4/19/96 10/30/02 */
2684 static Image *ReallyGetImage(name, w, h, pad, cp)
2685 char      *name;
2686 int       w, h, pad;
2687 ColorPair cp;
2688 {
2689     static const struct {
2690         char *name;
2691         void (*proc)();
2692         Bool use_rootGC;
2693         int state;
2694     } pmtab[] = {
2695         { TBPM_DOT,             DrawDotImage,           True, off  },
2696         { TBPM_ICONIFY,         DrawDotImage,           True, off  },
2697         { TBPM_RESIZE,          DrawResizeImage,        True, off  },
2698         { TBPM_MENU,            DrawMenuImage,          True, off  },
2699         { TBPM_XLOGO,           DrawXLogoImage,         True, off  },
2700         { TBPM_DELETE,          DrawXLogoImage,         True, off  },
2701         { TBPM_QUESTION,        DrawQuestionImage,      True, off  },
2702
2703         /* djhjr - 6/4/00 */
2704         { TBPM_RARROW,          DrawRArrowImage,        True, off  },
2705         { TBPM_DARROW,          DrawDArrowImage,        True, off  },
2706
2707         { TBPM_3DDOT,           Draw3DDotImage,         False, off },
2708         { TBPM_3DRESIZE,        Draw3DResizeImage,      False, off },
2709         { TBPM_3DMENU,          Draw3DMenuImage,        False, off },
2710         { TBPM_3DZOOM,          Draw3DZoomImage,        False, off },
2711         { TBPM_3DBAR,           Draw3DBarImage,         False, off },
2712
2713         /* djhjr - 6/4/00 */
2714         { TBPM_3DRARROW,        Draw3DRArrowImage,      False, off },
2715         { TBPM_3DDARROW,        Draw3DDArrowImage,      False, off },
2716
2717         /* djhjr - 10/30/02 */
2718         { TBPM_3DBOX,           Draw3DBoxHighlight,     False, off },
2719         { TBPM_3DLINES,         Draw3DLinesHighlight,   False, off },
2720     };
2721         
2722     Image *image = NULL;
2723     name_list **list;
2724     register int i;
2725     char fullname [256];
2726
2727     if (name == NULL) return (NULL);
2728
2729     list = &Scr->ImageCache;
2730
2731     if (name[0] == ':')
2732     {
2733         /* probably need '"%d", Scr->screen' - Caveh Frank Jalali */
2734         sprintf(fullname, "%s.%dx%d.%Xx%X", name,
2735                 w, h, (int)cp.fore, (int)cp.back);
2736         if ((image = (Image *)LookInNameList(*list, fullname)) == NULL)
2737         {
2738             for (i = 0; i < sizeof(pmtab) / sizeof(pmtab[0]); i++)
2739             {
2740                 if (XmuCompareISOLatin1(pmtab[i].name, name) == 0)
2741                 {
2742                     if (!(image = CreateImagePixmap(name, w, h, Scr->d_depth)))
2743                         return (None);
2744
2745                     DrawBackground(image->pixmap, 0, 0, w, h, cp,
2746                                 pmtab[i].use_rootGC | (Scr->Monochrome != COLOR));
2747
2748                     /* added d, x, y, w, h, pad, state - djhjr - 10/29/02 */
2749                     (*pmtab[i].proc)(image->pixmap, 0, 0, w, h, pad,
2750                                      cp, pmtab[i].state);
2751
2752                     image->mask   = None;
2753                     image->width  = w;
2754                     image->height = h;
2755                     image->next   = None;
2756                     break;
2757                 }
2758             }
2759
2760             if (!image)
2761             {
2762                 fprintf(stderr, "%s:  no such built-in pixmap \"%s\"\n",
2763                                 ProgramName, name);
2764                 return (NULL);
2765             }
2766         }
2767         else
2768             return (image);
2769     }
2770     else
2771     {
2772         /*
2773          * Need screen number in fullname since screens may have different GCs.
2774          * Submitted by Caveh Frank Jalali
2775          */
2776         sprintf(fullname, "%s.%Xx%X.%d",
2777                 name, (int)cp.fore, (int)cp.back, (int)Scr->screen);
2778         if ((image = (Image *)LookInNameList(*list, fullname)) == NULL)
2779         {
2780             if ((image = LoadBitmapImage(name, cp)) == NULL)
2781 #ifndef NO_XPM_SUPPORT
2782                 /* djhjr - 3/20/98 */
2783                 /* added color argument - djhjr - 9/28/99 */
2784                 image = FindImage(name, cp.back);
2785 #else
2786                 ;
2787 #endif
2788
2789             if (!image) return (NULL);
2790         }
2791         else
2792             return (image);
2793     }
2794
2795     /* added 'type' argument - djhjr - 10/20/01 */
2796     AddToList(list, fullname, LTYPE_EXACT_NAME, (char *)image);
2797
2798     return (image);
2799 }
2800
2801 /*
2802  * Wrapper to guarantee something is returned - djhjr - 10/30/02
2803  */
2804 Image *GetImage(name, w, h, pad, cp)
2805 char *name;
2806 int w, h, pad;
2807 ColorPair cp;
2808 {
2809     Image *image = NULL;
2810
2811     if (!(image = ReallyGetImage(name, w, h, pad, cp)))
2812         image = ReallyGetImage(TBPM_QUESTION, w, h, pad, cp);
2813
2814     return (image);
2815 }
2816
2817 /* djhjr - 4/21/96 */
2818 /* djhjr - 1/12/98 */
2819 void PaintBorders (tmp_win, focus)
2820 TwmWindow       *tmp_win;
2821 Bool            focus;
2822 {
2823         GC                      gc;
2824         ColorPair       cp;
2825         int                     i, j, cw, ch, cwbw, chbw;
2826 #ifdef USE_ORIGINAL_CORNERS
2827         int                     THbw, fhbwchbw, fhTHchbw;
2828 #endif
2829
2830         cp = (focus && tmp_win->highlight) ? tmp_win->border : tmp_win->border_tile;
2831
2832         /* no titlebar, no corners */
2833         if (tmp_win->title_height == 0)
2834         {
2835                 Draw3DBorder (tmp_win->frame,
2836                         0,
2837                         0,
2838                         tmp_win->frame_width,
2839                         tmp_win->frame_height,
2840                         Scr->BorderBevelWidth, cp, off, True, False);
2841                 Draw3DBorder (tmp_win->frame,
2842                         tmp_win->frame_bw3D - Scr->BorderBevelWidth,
2843                         tmp_win->frame_bw3D - Scr->BorderBevelWidth,
2844                         tmp_win->frame_width  - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderBevelWidth,
2845                         tmp_win->frame_height - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderBevelWidth,
2846                         Scr->BorderBevelWidth, cp, on, True, False);
2847
2848                 return;
2849         }
2850
2851         cw = ch = Scr->TitleHeight;
2852         if (cw * 2 > tmp_win->attr.width) cw = tmp_win->attr.width / 2;
2853         if (ch * 2 > tmp_win->attr.height) ch = tmp_win->attr.height / 2;
2854         cwbw = cw + tmp_win->frame_bw3D;
2855         chbw = ch + tmp_win->frame_bw3D;
2856
2857 #ifdef USE_ORIGINAL_CORNERS
2858         THbw = Scr->TitleHeight + tmp_win->frame_bw3D;
2859         fhbwchbw = tmp_win->frame_height + tmp_win->frame_bw3D - 3 * chbw;
2860         fhTHchbw = tmp_win->frame_height - (Scr->TitleHeight + ch + 2 * tmp_win->frame_bw3D);
2861
2862         /* client upper left corner */
2863         if (tmp_win->squeeze_info && tmp_win->title_x > tmp_win->frame_bw3D)
2864                 Draw3DCorner (tmp_win->frame,
2865                         0,
2866                         Scr->TitleHeight,
2867                         cwbw,
2868                         chbw,
2869                         tmp_win->frame_bw3D, Scr->BorderBevelWidth, cp, 0);
2870         /* client top bar */
2871         if (tmp_win->squeeze_info)
2872                 Draw3DBorder (tmp_win->frame,
2873                         THbw,
2874                         tmp_win->title_height,
2875                         tmp_win->frame_width - 2 * cwbw,
2876                         tmp_win->frame_bw3D,
2877                         Scr->BorderBevelWidth, cp, off, True, False);
2878         /* client upper right corner */
2879         if (tmp_win->squeeze_info && tmp_win->title_x + tmp_win->title_width + tmp_win->frame_bw3D < tmp_win->frame_width)
2880                 Draw3DCorner (tmp_win->frame,
2881                         tmp_win->frame_width  - cwbw,
2882                         Scr->TitleHeight,
2883                         cwbw,
2884                         chbw,
2885                         tmp_win->frame_bw3D, Scr->BorderBevelWidth, cp, 1);
2886         /* client left bar */
2887         if (tmp_win->squeeze_info && tmp_win->title_x > tmp_win->frame_bw3D)
2888                 Draw3DBorder (tmp_win->frame,
2889                         0,
2890                         THbw + ch,
2891                         tmp_win->frame_bw3D,
2892                         fhbwchbw,
2893                         Scr->BorderBevelWidth, cp, off, True, False);
2894         else
2895                 Draw3DBorder (tmp_win->frame,
2896                         0,
2897                         THbw,
2898                         tmp_win->frame_bw3D,
2899                         fhTHchbw,
2900                         Scr->BorderBevelWidth, cp, off, True, False);
2901         /* client right bar */
2902         if (tmp_win->squeeze_info && tmp_win->title_x + tmp_win->title_width + tmp_win->frame_bw3D < tmp_win->frame_width)
2903                 Draw3DBorder (tmp_win->frame,
2904                         tmp_win->frame_width  - tmp_win->frame_bw3D,
2905                         THbw + ch,
2906                         tmp_win->frame_bw3D,
2907                         fhbwchbw,
2908                         Scr->BorderBevelWidth, cp, off, True, False);
2909         else
2910                 Draw3DBorder (tmp_win->frame,
2911                         tmp_win->frame_width  - tmp_win->frame_bw3D,
2912                         THbw,
2913                         tmp_win->frame_bw3D,
2914                         fhTHchbw,
2915                         Scr->BorderBevelWidth, cp, off, True, False);
2916         /* client lower left corner */
2917         Draw3DCorner (tmp_win->frame,
2918                 0,
2919                 tmp_win->frame_height - chbw,
2920                 cwbw,
2921                 chbw,
2922                 tmp_win->frame_bw3D, Scr->BorderBevelWidth, cp, 3);
2923         /* client bottom bar */
2924         Draw3DBorder (tmp_win->frame,
2925                 THbw,
2926                 tmp_win->frame_height - tmp_win->frame_bw3D,
2927                 tmp_win->frame_width - 2 * cwbw,
2928                 tmp_win->frame_bw3D,
2929                 Scr->BorderBevelWidth, cp, off, True, False);
2930         /* client lower right corner */
2931         Draw3DCorner (tmp_win->frame,
2932                 tmp_win->frame_width  - cwbw,
2933                 tmp_win->frame_height - chbw,
2934                 cwbw,
2935                 chbw,
2936                 tmp_win->frame_bw3D, Scr->BorderBevelWidth, cp, 2);
2937
2938         /* titlebar upper left corner */
2939         Draw3DCorner (tmp_win->frame,
2940                 tmp_win->title_x - tmp_win->frame_bw3D,
2941                 0,
2942                 cwbw,
2943                 THbw,
2944                 tmp_win->frame_bw3D, Scr->BorderBevelWidth, cp, 0);
2945         /* titlebar top bar */
2946         Draw3DBorder (tmp_win->frame,
2947                 tmp_win->title_x + cw,
2948                 0,
2949                 tmp_win->title_width - 2 * cw,
2950                 tmp_win->frame_bw3D,
2951                 Scr->BorderBevelWidth, cp, off, True, False);
2952         /* titlebar upper right corner */
2953         Draw3DCorner (tmp_win->frame,
2954                 (tmp_win->title_width > 2 * Scr->TitleHeight)
2955                         ? tmp_win->title_x + tmp_win->title_width - Scr->TitleHeight
2956                         : tmp_win->frame_width - cwbw,
2957                 0,
2958                 cwbw,
2959                 THbw,
2960                 tmp_win->frame_bw3D, Scr->BorderBevelWidth, cp, 1);
2961 #else /* USE_ORIGINAL_CORNERS */
2962         /* client */
2963         borderdashoffset = 1;
2964         Draw3DBorder (tmp_win->frame,
2965                 0,
2966                 Scr->TitleHeight,
2967                 tmp_win->frame_width,
2968                 tmp_win->frame_height - Scr->TitleHeight,
2969                 Scr->BorderBevelWidth, cp, off, True, False);
2970         borderdashoffset = 1;
2971         Draw3DBorder (tmp_win->frame,
2972                 tmp_win->frame_bw3D - Scr->BorderBevelWidth,
2973                 Scr->TitleHeight + tmp_win->frame_bw3D - Scr->BorderBevelWidth,
2974                 tmp_win->frame_width  - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderBevelWidth,
2975                 tmp_win->frame_height - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderBevelWidth - Scr->TitleHeight,
2976                 Scr->BorderBevelWidth, cp, on, True, False);
2977     if (!Scr->NoBorderDecorations)      /* djhjr - 10/20/02 */
2978     {
2979         /* upper left corner */
2980         if (tmp_win->title_x == tmp_win->frame_bw3D)
2981                 Draw3DBevel (tmp_win->frame,
2982                         0, Scr->TitleHeight + tmp_win->frame_bw3D,
2983                         tmp_win->frame_bw3D, cp,
2984                         (Scr->BeNiceToColormap) ? on : off, 222);
2985         else
2986         {
2987                 if (tmp_win->title_x > tmp_win->frame_bw3D + cwbw)
2988                         Draw3DBevel (tmp_win->frame,
2989                                 cwbw, Scr->TitleHeight,
2990                                 tmp_win->frame_bw3D, cp,
2991                                 (Scr->BeNiceToColormap) ? on : off, 1);
2992                 Draw3DBevel (tmp_win->frame,
2993                         0, Scr->TitleHeight + chbw,
2994                         tmp_win->frame_bw3D, cp,
2995                         (Scr->BeNiceToColormap) ? on : off, 2);
2996         }
2997     }
2998         /* upper right corner */
2999         if ((i = tmp_win->title_x + tmp_win->title_width + tmp_win->frame_bw3D) == tmp_win->frame_width)
3000                 Draw3DBevel (tmp_win->frame,
3001                         tmp_win->frame_width - tmp_win->frame_bw3D, Scr->TitleHeight + tmp_win->frame_bw3D,
3002                         tmp_win->frame_bw3D, cp,
3003                         (Scr->BeNiceToColormap) ? on : off, 222);
3004         else
3005         {
3006             if (!Scr->NoBorderDecorations)      /* djhjr - 10/20/02 */
3007             {
3008                 if (i < tmp_win->frame_width - cwbw)
3009                         Draw3DBevel (tmp_win->frame,
3010                                 tmp_win->frame_width - cwbw, Scr->TitleHeight,
3011                                 tmp_win->frame_bw3D, cp,
3012                                 (Scr->BeNiceToColormap) ? on : off, 1);
3013                 Draw3DBevel (tmp_win->frame,
3014                         tmp_win->frame_width - tmp_win->frame_bw3D,
3015                         Scr->TitleHeight + chbw,
3016                         tmp_win->frame_bw3D, cp,
3017                         (Scr->BeNiceToColormap) ? on : off, 2);
3018             }
3019         }
3020     if (!Scr->NoBorderDecorations)      /* djhjr - 10/20/02 */
3021     {
3022         /* lower left corner */
3023         Draw3DBevel (tmp_win->frame,
3024                 cwbw, tmp_win->frame_height - tmp_win->frame_bw3D,
3025                 tmp_win->frame_bw3D, cp,
3026                 (Scr->BeNiceToColormap) ? on : off, 1);
3027         Draw3DBevel (tmp_win->frame,
3028                 0, tmp_win->frame_height - chbw,
3029                 tmp_win->frame_bw3D, cp,
3030                 (Scr->BeNiceToColormap) ? on : off, 2);
3031         /* lower right corner */
3032         Draw3DBevel (tmp_win->frame,
3033                 tmp_win->frame_width - cwbw,
3034                 tmp_win->frame_height - tmp_win->frame_bw3D,
3035                 tmp_win->frame_bw3D, cp,
3036                 (Scr->BeNiceToColormap) ? on : off, 1);
3037         Draw3DBevel (tmp_win->frame,
3038                 tmp_win->frame_width - tmp_win->frame_bw3D,
3039                 tmp_win->frame_height - chbw,
3040                 tmp_win->frame_bw3D, cp,
3041                 (Scr->BeNiceToColormap) ? on : off, 2);
3042     }
3043         /* title */
3044         borderdashoffset = 0;
3045         Draw3DBorder (tmp_win->frame,
3046                 tmp_win->title_x - tmp_win->frame_bw3D,
3047                 tmp_win->title_y - tmp_win->frame_bw3D,
3048                 tmp_win->title_width + 2 * tmp_win->frame_bw3D,
3049                 Scr->TitleHeight + tmp_win->frame_bw3D,
3050                 Scr->BorderBevelWidth, cp, off, True, False);
3051         borderdashoffset = 0;
3052         Draw3DBorder (tmp_win->frame,
3053                 tmp_win->title_x - Scr->BorderBevelWidth,
3054                 tmp_win->title_y - Scr->BorderBevelWidth,
3055                 tmp_win->title_width + 2 * Scr->BorderBevelWidth,
3056                 Scr->TitleHeight,
3057                 Scr->BorderBevelWidth, cp, on, True, False);
3058         /* upper left corner */
3059         if (tmp_win->title_x == tmp_win->frame_bw3D)
3060         {
3061             /* this 'if (...) else' - djhjr - 10/20/02 */
3062             if (Scr->NoBorderDecorations)
3063             {
3064                 Draw3DNoBevel(tmp_win->frame,
3065                         tmp_win->title_x - tmp_win->frame_bw3D,
3066                         Scr->TitleHeight + tmp_win->frame_bw3D,
3067                         tmp_win->frame_bw3D, cp,
3068                         (Scr->BeNiceToColormap) ? off : on, False);
3069             }
3070             else
3071             {
3072                 gc = setBevelGC(2, (Scr->BeNiceToColormap) ? on : off, cp);
3073
3074 /* djhjr - 4/29/98
3075                 XDrawLine (dpy, tmp_win->frame, gc,
3076                         tmp_win->title_x - 2, Scr->TitleHeight + tmp_win->frame_bw3D - 4,
3077                         tmp_win->title_x - 2, Scr->TitleHeight + tmp_win->frame_bw3D - 1);
3078                 XDrawLine (dpy, tmp_win->frame, gc,
3079                         tmp_win->title_x - 1, Scr->TitleHeight + tmp_win->frame_bw3D - 4,
3080                         tmp_win->title_x - 1, Scr->TitleHeight + tmp_win->frame_bw3D - 1);
3081 */
3082                 for (j = 1; j <= Scr->BorderBevelWidth; j++)
3083                         XDrawLine (dpy, tmp_win->frame, gc,
3084                                 tmp_win->title_x - j,
3085                                 Scr->TitleHeight + tmp_win->frame_bw3D - 2 * Scr->BorderBevelWidth,
3086                                 tmp_win->title_x - j,
3087                                 Scr->TitleHeight + tmp_win->frame_bw3D - Scr->BorderBevelWidth - 1);
3088
3089                 Draw3DBevel (tmp_win->frame,
3090                         tmp_win->title_x + cw, 0,
3091                         tmp_win->frame_bw3D, cp,
3092                         (Scr->BeNiceToColormap) ? on : off, 1);
3093             }
3094         }
3095         else
3096         {
3097                 Draw3DBevel (tmp_win->frame,
3098                         tmp_win->title_x - tmp_win->frame_bw3D, Scr->TitleHeight,
3099                         tmp_win->frame_bw3D, cp, off, 3);
3100         }
3101         /* upper right corner */
3102         if (i == tmp_win->frame_width)
3103         {
3104             /* this 'if (...) else' - djhjr - 10/20/02 */
3105             if (Scr->NoBorderDecorations)
3106             {
3107                 Draw3DNoBevel(tmp_win->frame,
3108                         tmp_win->frame_width - tmp_win->frame_bw3D,
3109                         Scr->TitleHeight + tmp_win->frame_bw3D,
3110                         tmp_win->frame_bw3D, cp,
3111                         (Scr->BeNiceToColormap) ? off : on, False);
3112             }
3113             else
3114             {
3115                 gc = setBevelGC(1, (Scr->BeNiceToColormap) ? off : on, cp);
3116
3117 /* djhjr - 4/29/98
3118                 gc = setBevelGC(1, on, cp);
3119                 XDrawLine (dpy, tmp_win->frame, gc,
3120                         tmp_win->title_x + tmp_win->title_width, Scr->TitleHeight + tmp_win->frame_bw3D - 2,
3121                         tmp_win->title_x + tmp_win->title_width, Scr->TitleHeight + tmp_win->frame_bw3D - 2);
3122 */
3123                 for (j = 0; j < Scr->BorderBevelWidth; j++)
3124                         XDrawLine (dpy, tmp_win->frame, gc,
3125                                 tmp_win->title_x + tmp_win->title_width - 1,
3126                                 Scr->TitleHeight + tmp_win->frame_bw3D - Scr->BorderBevelWidth + j - 1,
3127                                 tmp_win->title_x + tmp_win->title_width + Scr->BorderBevelWidth - j - 1,
3128                                 Scr->TitleHeight + tmp_win->frame_bw3D - Scr->BorderBevelWidth + j - 1);
3129
3130                 Draw3DBevel (tmp_win->frame,
3131                         tmp_win->title_x + tmp_win->title_width - cw, 0,
3132                         tmp_win->frame_bw3D, cp,
3133                         (Scr->BeNiceToColormap) ? on : off, 1);
3134             }
3135         }
3136         else
3137         {
3138                 Draw3DBevel (tmp_win->frame,
3139                         tmp_win->title_x + tmp_win->title_width, Scr->TitleHeight,
3140                         tmp_win->frame_bw3D, cp, off, 4);
3141         }
3142 #endif /* USE_ORIGINAL_CORNERS */
3143 }
3144
3145 /* djhjr - 4/21/96 */
3146 void PaintIcon (tmp_win)
3147 TwmWindow *tmp_win;
3148 {
3149 /* djhjr - 5/5/98
3150     if (Scr->use3Diconmanagers) {
3151 */
3152         /* was 'Scr->use3Dicons' - djhjr - 8/11/98 */
3153     if (Scr->IconBevelWidth > 0) {
3154
3155 /*
3156         Draw3DBorder (tmp_win->icon_w, 0, tmp_win->icon_height,
3157                 tmp_win->icon_w_width, Scr->IconFont.height + 6,
3158                 Scr->BorderBevelWidth, tmp_win->iconc, off, False, False);
3159 */
3160         /* was 'Scr->BorderBevelWidth' - djhjr - 8/11/98 */
3161         Draw3DBorder (tmp_win->icon_w, 0, 0,
3162                 tmp_win->icon_w_width, tmp_win->icon_w_height,
3163                 Scr->IconBevelWidth, tmp_win->iconc, off, False, False);
3164     }
3165
3166     /* font was font.font->fid - djhjr - 9/14/03 */
3167     FBF(tmp_win->iconc.fore, tmp_win->iconc.back, Scr->IconFont);
3168
3169 /* djhjr - 9/14/03 */
3170 #ifndef NO_I18N_SUPPORT
3171         MyFont_DrawString (dpy, tmp_win->icon_w, &Scr->IconFont,
3172 #else
3173         XDrawString (dpy, tmp_win->icon_w,
3174 #endif
3175                 Scr->NormalGC, tmp_win->icon_x, tmp_win->icon_y, 
3176                 tmp_win->icon_name, strlen(tmp_win->icon_name));
3177 }
3178
3179 /* djhjr - 4/20/96 */
3180 void PaintTitle (tmp_win)
3181 TwmWindow *tmp_win;
3182 {
3183         /* made static - djhjr - 6/18/99 */
3184         static int en = 0, dots = 0;
3185
3186         int bwidth = Scr->TBInfo.width + Scr->TBInfo.pad;
3187         int left = (Scr->TBInfo.nleft) ? Scr->TBInfo.leftx +
3188                    (Scr->TBInfo.nleft * bwidth) - Scr->TBInfo.pad :
3189                    0;
3190         int right = (Scr->TBInfo.nright) ?
3191                     (Scr->TBInfo.nright * bwidth) - Scr->TBInfo.pad :
3192                     0;
3193
3194         /* djhjr - 3/29/98 */
3195         int i, j, slen = strlen(tmp_win->name);
3196         char *a = NULL;
3197
3198 /* djhjr - 9/14/03 */
3199 #ifndef NO_I18N_SUPPORT
3200         if (!en) en = MyFont_TextWidth(&Scr->TitleBarFont, "n", 1);
3201 #else
3202         if (!en) en = XTextWidth(Scr->TitleBarFont.font, "n", 1);
3203 #endif
3204
3205         /*
3206          * clip the title a couple of characters less than the width of
3207          * the titlebar plus padding, and tack on ellipses - this is a
3208          * little different than the icon manager's...
3209          *
3210          * djhjr - 3/29/98
3211          */
3212         if (Scr->NoPrettyTitles == FALSE) /* for rader - djhjr - 2/9/99 */
3213         {
3214 /* djhjr - 9/14/03 */
3215 #ifndef NO_I18N_SUPPORT
3216                 i = MyFont_TextWidth(&Scr->TitleBarFont, tmp_win->name, slen);
3217 #else
3218                 i = XTextWidth(Scr->TitleBarFont.font, tmp_win->name, slen);
3219 #endif
3220
3221 /* DUH! - djhjr - 6/18/99
3222                 j = tmp_win->title_width - 2 * Scr->TBInfo.rightoff;
3223 */
3224 /* djhjr - 10/18/02
3225                 if (!dots) dots = XTextWidth(Scr->TitleBarFont.font, "...", 3) + en;
3226                 j = tmp_win->title_width - Scr->TBInfo.titlex - Scr->TBInfo.rightoff - dots;
3227 */
3228 /* djhjr - 9/14/03 */
3229 #ifndef NO_I18N_SUPPORT
3230                 if (!dots) dots = MyFont_TextWidth(&Scr->TitleBarFont, "...", 3);
3231 #else
3232                 if (!dots) dots = XTextWidth(Scr->TitleBarFont.font, "...", 3);
3233 #endif
3234                 j = tmp_win->title_width - Scr->TBInfo.titlex - Scr->TBInfo.rightoff - en;
3235
3236 /* djhjr - 10/18/02
3237                 * djhjr - 5/5/98 *
3238                 * was 'Scr->use3Dtitles' - djhjr - 8/11/98 *
3239                 if (Scr->TitleBevelWidth > 0)
3240                         j -= Scr->TitleBevelWidth;
3241 */
3242                 /* reworked this stuff - djhjr - 10/18/02 */
3243                 if (dots >= j)
3244                         slen = 0;
3245                 else if (i > j)
3246                 {
3247                         while (i >= 0)
3248                         {
3249 /* djhjr - 9/14/03 */
3250 #ifndef NO_I18N_SUPPORT
3251                                 if (MyFont_TextWidth(&Scr->TitleBarFont,
3252 #else
3253                                 if (XTextWidth(Scr->TitleBarFont.font,
3254 #endif
3255                                                 tmp_win->name, i) + dots < j)
3256                                 {
3257                                         slen = i;
3258                                         break;
3259                                 }
3260
3261                                 i--;
3262                         }
3263
3264                         a = (char *)malloc(slen + 4);
3265                         memcpy(a, tmp_win->name, slen);
3266                         strcpy(a + slen, "...");
3267                         slen += 3;
3268                 }
3269         }
3270
3271     /* font was font.font->fid - djhjr - 9/14/03 */
3272     FBF(tmp_win->title.fore, tmp_win->title.back, Scr->TitleBarFont);
3273
3274 /* djhjr - 10/18/02 */
3275 #if 0
3276         /* was 'Scr->use3Dtitles' - djhjr - 8/11/98 */
3277     if (Scr->TitleBevelWidth > 0)
3278         {
3279 /* djhjr - 9/14/03 */
3280 #ifndef NO_I18N_SUPPORT
3281             MyFont_DrawString (dpy, tmp_win->title_w, &Scr->TitleBarFont,
3282 #else
3283             XDrawString (dpy, tmp_win->title_w,
3284 #endif
3285                  Scr->NormalGC,
3286 /* djhjr - 4/29/98
3287                  Scr->TBInfo.titlex + en, Scr->TitleBarFont.y + 2, 
3288 */
3289 /* djhjr - 5/5/98
3290                  Scr->TBInfo.titlex + en, Scr->TitleBarFont.y + Scr->TitleBevelWidth + 1, 
3291 */
3292                  Scr->TBInfo.titlex + Scr->TitleBevelWidth + en, Scr->TitleBarFont.y, 
3293
3294                  (a) ? a : tmp_win->name, slen);
3295         }
3296     else
3297 #endif
3298 /* djhjr - 9/14/03 */
3299 #ifndef NO_I18N_SUPPORT
3300         MyFont_DrawString (dpy, tmp_win->title_w, &Scr->TitleBarFont,
3301 #else
3302         XDrawString (dpy, tmp_win->title_w,
3303 #endif
3304                  Scr->NormalGC, Scr->TBInfo.titlex, Scr->TitleBarFont.y,
3305                  (a) ? a : tmp_win->name, slen);
3306
3307         /* free the clipped title - djhjr - 3/29/98 */
3308         if (a) free(a);
3309
3310         /* was 'Scr->use3Dtitles' - djhjr - 8/11/98 */
3311         if (Scr->TitleBevelWidth > 0)
3312         {
3313 /*
3314             Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0,
3315                 tmp_win->title_width - Scr->TBInfo.titlex - Scr->TBInfo.rightoff,
3316                 Scr->TitleHeight, Scr->TitleBevelWidth, tmp_win->title, off, True, False);
3317 */
3318 /* djhjr - 3/12/97
3319             Draw3DBorder (tmp_win->title_w, Scr->TBInfo.rightoff, Scr->FramePadding,
3320                 tmp_win->title_width - 2 * Scr->TBInfo.rightoff,
3321                 Scr->TitleHeight - 2 * Scr->FramePadding, Scr->TitleBevelWidth, tmp_win->title, off, True, False);
3322 */
3323 /* djhjr - 10/17/02
3324             Draw3DBorder (tmp_win->title_w, Scr->TBInfo.leftx + left,
3325                 Scr->FramePadding, tmp_win->title_width - (left + right),
3326                 Scr->TitleHeight - 2 * Scr->FramePadding, Scr->TitleBevelWidth, tmp_win->title, off, False, False);
3327 */
3328             if (Scr->FramePadding + Scr->ButtonIndent > 0)
3329             {
3330                 Draw3DBorder(tmp_win->title_w, 0, 0,
3331                              tmp_win->title_width, Scr->TitleHeight,
3332                              Scr->TitleBevelWidth, tmp_win->title,
3333                              off, False, False);
3334             }
3335             else
3336             {
3337                 Draw3DBorder(tmp_win->title_w, left, 0,
3338                              tmp_win->title_width - (left + right),
3339                              Scr->TitleHeight,
3340                              Scr->TitleBevelWidth, tmp_win->title,
3341                              off, False, False);
3342             }
3343         }
3344 }
3345
3346 /* djhjr - 11/17/97 */
3347 /* collapsed the two functions PTB() and PTBH() - djhjr - 8/10/98 */
3348 /* djhjr - 10/30/02 */
3349 void PaintTitleButton(tmp_win, tbw, onoroff)
3350 TwmWindow *tmp_win;
3351 TBWindow  *tbw;
3352 int onoroff; /* 0 = no hilite    1 = hilite off    2 = hilite on */
3353 {
3354     Image *image;
3355     TitleButton *tb;
3356     /* djhjr - 5/23/98 8/10/98 */
3357     ColorPair cp;
3358
3359     if (!tbw->window) return;
3360
3361     tb = tbw->info;
3362
3363     /* djhjr - 5/23/98 8/10/98 */
3364     if (Scr->ButtonColorIsFrame)
3365         cp = (onoroff == 2) ? tmp_win->border : tmp_win->border_tile;
3366     else
3367         cp = tmp_win->title;
3368     cp.fore = tmp_win->title.fore;
3369
3370     image = GetImage(tb->name, tb->width, tb->height,
3371                      Scr->ButtonBevelWidth * 2, cp);
3372
3373     XCopyArea(dpy, image->pixmap, tbw->window, Scr->NormalGC,
3374               tb->srcx, tb->srcy, tb->width, tb->height, tb->dstx, tb->dsty);
3375
3376     /* djhjr - 8/10/98 8/18/98 */
3377     /* was 'Scr->TitleBevelWidth' - djhjr - 8/11/98 */
3378     if (Scr->ButtonBevelWidth > 0)
3379         Draw3DBorder(tbw->window, 0, 0, tb->width, tb->height,
3380                      Scr->ButtonBevelWidth, cp, off, False, False);
3381 }
3382
3383 /* djhjr - 4/19/96 */
3384 /* re-arranged - djhjr - 4/5/98 */
3385 void PaintTitleHighlight(tmp_win, onoroff)
3386 TwmWindow *tmp_win;
3387 Bool onoroff;
3388 {
3389         /* djhjr - 4/3/98 */
3390         if (!tmp_win->titlehighlight) return;
3391
3392         if (tmp_win->hilite_w)
3393         {
3394                 if (onoroff == on)
3395                         XMapWindow (dpy, tmp_win->hilite_w);
3396                 else
3397                         XUnmapWindow (dpy, tmp_win->hilite_w);
3398         }
3399         else if (Scr->hiliteName && tmp_win->title_height != 0)
3400                 DrawTitleHighlight(tmp_win, onoroff);   /* djhjr - 10/25/02 */
3401 }
3402
3403 /* djhjr - 4/2/98 10/18/02 */
3404 int ComputeHighlightWindowWidth(tmp_win)
3405 TwmWindow *tmp_win;
3406 {
3407 /* djhjr - 9/14/03 */
3408 #ifndef NO_I18N_SUPPORT
3409         int en = MyFont_TextWidth(&Scr->TitleBarFont, "n", 1);
3410 #else
3411         int en = XTextWidth(Scr->TitleBarFont.font, "n", 1);
3412 #endif
3413
3414         return (tmp_win->rightx - tmp_win->highlightx - en);
3415 }
3416