dtcm: Coverity 88353
[oweals/cde.git] / cde / programs / dtwm / WmGraphics.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* 
24  * (c) Copyright 1989, 1990, 1991, 1992 OPEN SOFTWARE FOUNDATION, INC. 
25  * ALL RIGHTS RESERVED 
26 */ 
27 /* 
28  * Motif Release 1.2
29 */
30 /*
31  * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
32
33 /*
34  * Included Files:
35  */
36
37 #include "WmGlobal.h"
38
39 #include <stdio.h>
40 #include <X11/Xlib.h>
41 #include <X11/StringDefs.h>
42 #include <X11/Xutil.h>
43 #include <X11/Intrinsic.h>
44 #include <X11/X.h>
45 #include <Xm/Xm.h>
46
47
48 #define RLIST_EXTENSION_SIZE    10
49
50 #ifndef MIN
51 #define MAX(x,y) ((x)>(y)?(x):(y))
52 #endif
53
54 /*
55  * include extern functions
56  */
57 #include "WmGraphics.h"
58 #include "WmError.h"
59
60
61
62 /*
63  * Global Variables:
64  */
65
66
67 /*
68  * Macros:
69  */
70
71 /* test if > 0 and return 1 if true, 0 if false. */
72 #define GE1(x) ((x)>0?1:0)
73
74
75 \f
76 /*************************************<->*************************************
77  *
78  *   Procedure: BevelRectangle (prTop, prBot, x, y, 
79  *                      width, height, top_wid, right_wid, bot_wid, left_wid)
80  *
81  *  Description:
82  *  -----------
83  *  Generate data for top- and bottom-shadow bevels on a box.
84  *
85  *  Inputs:
86  *  ------
87  *  prTop       - ptr to top shadow RList
88  *  prBot       - ptr to bottom shadow RList
89  *  x,y         - position of rectangle to bevel
90  *  width       - (outside) width of rectangle
91  *  height      - (outside) height of rectangle
92  *  top_wid     - width of beveling on top side of rectangle
93  *  right_wid   - width of beveling on right side of rectangle
94  *  bot_wid     - width of beveling on bottom side of rectangle
95  *  left_wid    - width of beveling on left side of rectangle
96  * 
97  *  Outputs:
98  *  -------
99  *  prTop       - top shadows for this rectangle added to list
100  *  prBot       - bottom shadows for this rectangle added to list
101  *  
102  *
103  *  Comments:
104  *  --------
105  *
106  *************************************<->***********************************/
107
108 void BevelRectangle (RList *prTop, RList *prBot, int x, int y, unsigned int width, unsigned int height, unsigned int top_wid, unsigned int right_wid, unsigned int bot_wid, unsigned int left_wid)
109 {
110     XRectangle *prect;          /* pointer to "current" rectangle */
111     int count;          /* counter used for beveling operation */
112     int join1, join2;           /* used to compute "good" bevel joints */
113     int x1, y1, len;            /* used to compute bevel parameters */
114     int *piTop, *piBot;
115
116
117     /* build the rectangles to implement the beveling on each side */
118
119     /* top side */
120
121     if (((prTop->used + (top_wid + left_wid)) > prTop->allocated) &&
122         (!ExtendRList (prTop, MAX (top_wid+left_wid, RLIST_EXTENSION_SIZE))))
123     {
124         return;         /* not enough memory */
125     }
126
127     piTop = &(prTop->used);
128     prect = &(prTop->prect[*piTop]);
129
130     join1 = left_wid;
131     join2 = right_wid;
132     x1 = x;
133     y1 = y;
134     len = width;
135     for (count=top_wid; count>0; count--, prect++, (*piTop)++) 
136     {
137         prect->x = x1;
138         prect->y = y1;
139         prect->width = len;
140         prect->height = 1;
141         x1 += GE1(--join1);
142         y1 += 1;
143         len -= GE1(join1) + GE1(--join2);
144     }
145
146     /* left side */
147
148     join1 = top_wid;
149     join2 = bot_wid;
150     x1 = x;
151     y1 = y+GE1(join1);
152     len = height-GE1(join1);
153     for (count=left_wid; count >0; count--, prect++, (*piTop)++) 
154     {   
155         prect->x = x1;
156         prect->y = y1;
157         prect->width = 1;
158         prect->height = len;
159         x1 += 1;
160         y1 += GE1(--join1);
161         len -= GE1(join1) + GE1(--join2);
162     }
163
164
165     /* bottom side */
166
167     if (((prBot->used + (bot_wid + right_wid)) > prBot->allocated) &&
168         (!ExtendRList(prBot, MAX (bot_wid+right_wid, RLIST_EXTENSION_SIZE))))
169     {
170         return;
171     }
172
173     piBot = &(prBot->used);
174     prect = &(prBot->prect[*piBot]);
175
176     join1 = left_wid;
177     join2 = right_wid;
178     x1 = x+GE1(join1);
179     y1 = y+height-1;
180     len = width-GE1(join1);
181     /* fudge fat bottom shadow to overwrite corner of skinny left shadow */
182     if (GE1(join1) && (bot_wid > left_wid)) {
183         len++;
184         x1--;
185         join1++;
186     }
187     for (count=bot_wid; count >0; count--, prect++, (*piBot)++) 
188     {
189         prect->x = x1;
190         prect->y = y1;
191         prect->width = len;
192         prect->height = 1;
193         x1 += GE1(--join1);
194         y1 -= 1;
195         len -= GE1(join1) + GE1(--join2);
196     }
197
198     /* right side */
199
200     join1 = top_wid;
201     join2 = bot_wid;
202     x1 = x+width-1;
203     y1 = y+GE1(join1);
204     len = height - GE1(join1) - GE1(join2);
205     /* fudge fat right shadow to overwrite corner of skinny top shadow */
206     if (GE1(join1) && (right_wid > top_wid)) {
207         len++;
208         y1--;
209         join1++;
210     }
211     for (count=right_wid; count >0; count--, prect++, (*piBot)++) 
212     {
213         prect->x = x1;
214         prect->y = y1;
215         prect->width = 1;
216         prect->height = len;
217         x1 -= 1;
218         y1 += GE1(--join1);
219         len -= GE1(join1) + GE1(--join2);
220     }
221
222 } /* END OF FUNCTION BevelRectangle */
223
224
225
226 \f
227 /*************************************<->*************************************
228  *
229  *   Procedure: BevelDepressedRectangle (prTop, prBot, x, y, 
230  *                      width, height, top_wid, right_wid, bot_wid, left_wid
231  *                      in_wid)
232  *
233  *  Description:
234  *  -----------
235  *  Generate data for top- and bottom-shadow bevels on a rectangle with
236  *  the center part depressed.
237  *
238  *  Inputs:
239  *  ------
240  *  prTop       - ptr to top shadow RList
241  *  prBot       - ptr to bottom shadow RList
242  *  x,y         - position of rectangle to bevel
243  *  width       - (outside) width of rectangle
244  *  height      - (outside) height of rectangle
245  *  top_wid     - width of beveling on top side of rectangle
246  *  right_wid   - width of beveling on right side of rectangle
247  *  bot_wid     - width of beveling on bottom side of rectangle
248  *  left_wid    - width of beveling on left side of rectangle
249  *  in_wid      - width of depressed beveling inside of rectangle
250  * 
251  *  Outputs:
252  *  -------
253  *  prTop       - top shadows for this rectangle added to list
254  *  prBot       - bottom shadows for this rectangle added to list
255  *  
256  *
257  *  Comments:
258  *  --------
259  *
260  *************************************<->***********************************/
261
262 void BevelDepressedRectangle (RList *prTop, RList *prBot, int x, int y, unsigned int width, unsigned int height, unsigned int top_wid, unsigned int right_wid, unsigned int bot_wid, unsigned int left_wid, unsigned int in_wid)
263 {
264     XRectangle *prect;          /* pointer to "current" rectangle */
265     int count;          /* counter used for beveling operation */
266     int join1, join2;           /* used to compute "good" bevel joints */
267     int x1, y1, len;            /* used to compute bevel parameters */
268     int *piTop, *piBot;
269
270
271     /* 
272      *  Build the rectangles to implement the beveling on each side 
273      *  First, guarantee that there is enough memory.
274      */
275
276
277     if (((prTop->used + (top_wid + left_wid)) > prTop->allocated) &&
278         (!ExtendRList (prTop, MAX (top_wid+left_wid, RLIST_EXTENSION_SIZE))))
279     {
280         return;         /* not enough memory */
281     }
282
283     if (((prBot->used + (bot_wid + right_wid)) > prBot->allocated) &&
284         (!ExtendRList(prBot, MAX (bot_wid+right_wid, RLIST_EXTENSION_SIZE))))
285     {
286         return;         /* not enought memory */
287     }
288
289
290
291     /* top side (normal beveling) */
292
293     piTop = &(prTop->used);
294     prect = &(prTop->prect[*piTop]);
295
296     join1 = left_wid;
297     join2 = right_wid;
298     x1 = x;
299     y1 = y;
300     len = width;
301     for (count=top_wid - in_wid; count>0; count--, prect++, (*piTop)++) 
302     {
303         prect->x = x1;
304         prect->y = y1;
305         prect->width = len;
306         prect->height = 1;
307         x1 += GE1(--join1);
308         y1 += 1;
309         len -= GE1(join1) + GE1(--join2);
310     }
311
312     /* top side (inverted beveling) */
313
314     piBot = &(prBot->used);
315     prect = &(prBot->prect[*piBot]);
316
317     for (count=in_wid; count>0; count--, prect++, (*piBot)++) 
318     {
319         prect->x = x1;
320         prect->y = y1;
321         prect->width = len;
322         prect->height = 1;
323         x1 += GE1(--join1);
324         y1 += 1;
325         len -= GE1(join1) + GE1(--join2);
326     }
327
328
329
330     /* left side (normal beveling) */
331
332     piTop = &(prTop->used);
333     prect = &(prTop->prect[*piTop]);
334
335     join1 = top_wid;
336     join2 = bot_wid;
337     x1 = x;
338     y1 = y+GE1(join1);
339     len = height-GE1(join1);
340     for (count=left_wid-in_wid; count >0; count--, prect++, (*piTop)++) 
341     {   
342         prect->x = x1;
343         prect->y = y1;
344         prect->width = 1;
345         prect->height = len;
346         x1 += 1;
347         y1 += GE1(--join1);
348         len -= GE1(join1) + GE1(--join2);
349     }
350
351     /* left side (inverted beveling) */
352
353     piBot = &(prBot->used);
354     prect = &(prBot->prect[*piBot]);
355
356     for (count=in_wid; count >0; count--, prect++, (*piBot)++) 
357     {   
358         prect->x = x1;
359         prect->y = y1;
360         prect->width = 1;
361         prect->height = len;
362         x1 += 1;
363         y1 += GE1(--join1);
364         len -= GE1(join1) + GE1(--join2);
365     }
366
367
368
369     /* bottom side (normal beveling) */
370
371     piBot = &(prBot->used);
372     prect = &(prBot->prect[*piBot]);
373
374     join1 = left_wid;
375     join2 = right_wid;
376     x1 = x+GE1(join1);
377     y1 = y+height-1;
378     len = width-GE1(join1);
379     /* fudge fat bottom shadow to overwrite corner of skinny left shadow */
380     if (GE1(join1) && (bot_wid > left_wid)) {
381         len++;
382         x1--;
383         join1++;
384     }
385     for (count=bot_wid-in_wid; count >0; count--, prect++, (*piBot)++) 
386     {
387         prect->x = x1;
388         prect->y = y1;
389         prect->width = len;
390         prect->height = 1;
391         x1 += GE1(--join1);
392         y1 -= 1;
393         len -= GE1(join1) + GE1(--join2);
394     }
395
396     /* bottom side (inverted beveling) */
397
398     piTop = &(prTop->used);
399     prect = &(prTop->prect[*piTop]);
400
401     for (count=in_wid; count >0; count--, prect++, (*piTop)++) 
402     {
403         prect->x = x1;
404         prect->y = y1;
405         prect->width = len;
406         prect->height = 1;
407         x1 += GE1(--join1);
408         y1 -= 1;
409         len -= GE1(join1) + GE1(--join2);
410     }
411
412
413
414     /* right side (normal beveling) */
415
416     piBot = &(prBot->used);
417     prect = &(prBot->prect[*piBot]);
418
419     join1 = top_wid;
420     join2 = bot_wid;
421     x1 = x+width-1;
422     y1 = y+GE1(join1);
423     len = height - GE1(join1) - GE1(join2);
424     /* fudge fat right shadow to overwrite corner of skinny top shadow */
425     if (GE1(join1) && (right_wid > top_wid)) {
426         len++;
427         y1--;
428         join1++;
429     }
430     for (count=right_wid-in_wid; count >0; count--, prect++, (*piBot)++) 
431     {
432         prect->x = x1;
433         prect->y = y1;
434         prect->width = 1;
435         prect->height = len;
436         x1 -= 1;
437         y1 += GE1(--join1);
438         len -= GE1(join1) + GE1(--join2);
439     }
440
441     /* right side (inverted beveling) */
442
443     piTop = &(prTop->used);
444     prect = &(prTop->prect[*piTop]);
445
446     for (count=in_wid; count >0; count--, prect++, (*piTop)++) 
447     {
448         prect->x = x1;
449         prect->y = y1;
450         prect->width = 1;
451         prect->height = len;
452         x1 -= 1;
453         y1 += GE1(--join1);
454         len -= GE1(join1) + GE1(--join2);
455     }
456
457 } /* END OF FUNCTION BevelDepressedRectangle */
458
459
460
461 \f
462 /*************************************<->*************************************
463  *
464  *   Procedure: StretcherCorner (prTop, prBot, x, y, cnum, 
465  *                               swidth,  cwidth, cheight);
466  *
467  *  Description:
468  *  -----------
469  *  Generate data to draw a corner of the stretcher border.
470  *
471  *  Inputs:
472  *  ------
473  *  prTop       - ptr to top shadow RList
474  *  prBot       - ptr to bottom shadow RList
475  *  x,y         - position of rectangle enclosing the cornern
476  *  cnum        - corner number; which corner to draw
477  *                ASSUMES only NW, NE, SE, SW for mwm ()
478  *  swidth      - width (thickness) of border (includes bevels)
479  *  cwidth      - corner width from corner to end of horizontal run
480  *  cheight     - corner height from corner to end of vertical run
481  * 
482  *  Outputs:
483  *  -------
484  *  prTop       - array filled in for top shadows 
485  *  prBot       - array filledin for bottom shadows
486  *
487  *  Comments:
488  *  --------
489  *  o Uses only 1 pixel bevels. Beveling is hard coded.
490  *  o XFillRectangles assumed as an optimization to take
491  *    advantage of the block mover hardware.
492  *
493  *************************************<->***********************************/
494
495 void StretcherCorner (RList *prTop, RList *prBot, int x, int y, int cnum, unsigned int swidth, unsigned int cwidth, unsigned int cheight)
496 {
497     XRectangle *prect;          /* pointer to "current" rectangle */
498     int *piTop, *piBot;
499
500     switch (cnum) {
501
502         case STRETCH_NORTH_WEST:
503                 if (((prTop->used + 4) > prTop->allocated) &&
504                     (!ExtendRList (prTop, (unsigned int) RLIST_EXTENSION_SIZE)))
505                 {
506                     return;
507                 }
508
509                 piTop = &(prTop->used);
510                 prect = &(prTop->prect[*piTop]);
511
512                 prect->x = x;                   /* top (row 1) */
513                 prect->y = y;
514                 prect->width = cwidth;
515                 prect->height = 1;
516                 prect++;
517                 (*piTop)++;
518
519                 prect->x = x+1;                 /* top (row 2) */
520                 prect->y = y+1;
521                 prect->width = cwidth-2;
522                 prect->height = 1;
523                 prect++;
524                 (*piTop)++;
525
526                 prect->x = x;                   /* left (col 1) */
527                 prect->y = y+1;
528                 prect->width = 1;
529                 prect->height = cheight-1;
530                 prect++;
531                 (*piTop)++;
532
533                 prect->x = x+1;                 /* left (col 2) */
534                 prect->y = y+2;
535                 prect->width = 1;
536                 prect->height = cheight-3;
537                 (*piTop)++;
538
539                 if (((prBot->used + 4) > prBot->allocated) &&
540                     (!ExtendRList (prBot, (unsigned int) RLIST_EXTENSION_SIZE)))
541                 {
542                     return;
543                 }
544
545                 piBot = &(prBot->used);
546                 prect = &(prBot->prect[*piBot]); /* bottom shadow parts */
547
548
549                 prect->x = x+1;                 /* bottom end */
550                 prect->y = y+cheight-1;
551                 prect->width = swidth-1;
552                 prect->height = 1;
553                 prect++;
554                 (*piBot)++;
555
556                 if (wmGD.frameStyle == WmRECESSED)
557                 {
558                     prect->x = x+swidth-1;              /* right inside */
559                     prect->y = y+swidth-1;
560                     prect->width = 1;
561                     prect->height = cheight-swidth;
562                     prect++;
563                     (*piBot)++;
564
565                     prect->x = x+swidth;                /* bottom inside */
566                     prect->y = y+swidth-1;
567                     prect->width = cwidth-swidth;
568                     prect->height = 1;
569                     prect++;
570                     (*piBot)++;
571                 }
572
573                 prect->x = x+cwidth-1;          /* right end */
574                 prect->y = y+1;
575                 prect->width = 1;
576                 prect->height = swidth-1-((wmGD.frameStyle == WmSLAB)? 0 : 1);
577                 (*piBot)++;
578
579                 break;
580
581         case STRETCH_NORTH_EAST:
582                 if (((prTop->used + 4) > prTop->allocated) &&
583                     (!ExtendRList (prTop, (unsigned int) RLIST_EXTENSION_SIZE)))
584                 {
585                     return;
586                 }
587
588                 piTop = &(prTop->used);
589                 prect = &(prTop->prect[*piTop]);
590
591                 prect->x = x;                   /* top (row 1) */
592                 prect->y = y;
593                 prect->width = cwidth;
594                 prect->height = 1;
595                 prect++;
596                 (*piTop)++;
597
598                 prect->x = x+1;                 /* top (row 2) */
599                 prect->y = y+1;
600                 prect->width = cwidth-2;
601                 prect->height = 1;
602                 prect++;
603                 (*piTop)++;
604
605                 prect->x = x;                   /* left end */
606                 prect->y = y+1;
607                 prect->width = 1;
608                 prect->height = swidth-1;
609                 prect++;
610                 (*piTop)++;
611
612                 if (wmGD.frameStyle == WmRECESSED)
613                 {
614                     prect->x = x+cwidth-swidth; /* left inside (col 1) */
615                     prect->y = y+swidth;
616                     prect->width = 1;
617                     prect->height = cheight-swidth;
618                     (*piTop)++;
619                 }
620
621                 if (((prBot->used + 4) > prBot->allocated) &&
622                     (!ExtendRList (prBot, (unsigned int) RLIST_EXTENSION_SIZE)))
623                 {
624                     return;
625                 }
626
627                 piBot = &(prBot->used);
628                 prect = &(prBot->prect[*piBot]); /* bottom shadow parts */
629
630
631                 /* bottom end */
632                 prect->x = x+cwidth-swidth+((wmGD.frameStyle == WmSLAB)? 0 : 1);
633                 prect->y = y+cheight-1;
634                 prect->width = swidth-((wmGD.frameStyle == WmSLAB)? 0 : 1);
635                 prect->height = 1;
636                 prect++;
637                 (*piBot)++;
638
639                 prect->x = x+cwidth-1;          /* right (col 2) */
640                 prect->y = y+1;
641                 prect->width = 1;
642                 prect->height = cheight-2;
643                 prect++;
644                 (*piBot)++;
645
646                 prect->x = x+cwidth-2;          /* right (col 1) */
647                 prect->y = y+2;
648                 prect->width = 1;
649                 prect->height = cheight-3;
650                 prect++;
651                 (*piBot)++;
652
653                 if (wmGD.frameStyle == WmRECESSED)
654                 {
655                     prect->x = x+1;             /* bottom inside (row 2) */
656                     prect->y = y+swidth-1;
657                     prect->width = cwidth-swidth;
658                     prect->height = 1;
659                     (*piBot)++;
660                 }
661
662                 break;
663
664         case STRETCH_SOUTH_EAST:
665                 if (((prTop->used + 4) > prTop->allocated) &&
666                     (!ExtendRList (prTop, (unsigned int) RLIST_EXTENSION_SIZE)))
667                 {
668                     return;
669                 }
670
671                 piTop = &(prTop->used);
672                 prect = &(prTop->prect[*piTop]);
673
674                 if (wmGD.frameStyle == WmRECESSED)
675                 {
676                     prect->x = x;                       /* top inside */
677                     prect->y = y+cheight-swidth;
678                     prect->width = cwidth-swidth+1;
679                     prect->height = 1;
680                     prect++;
681                     (*piTop)++;
682
683                     prect->x = x+cwidth-swidth; /* left inside */
684                     prect->y = y;
685                     prect->width = 1;
686                     prect->height = cheight-swidth;
687                     prect++;
688                     (*piTop)++;
689                 }
690
691                 /* top end */
692                 prect->x = x+cwidth-swidth+
693                                 ((wmGD.frameStyle == WmSLAB)? 0 : 1);
694                 prect->y = y;
695                 prect->width = swidth-2+((wmGD.frameStyle == WmSLAB)? 1 : 0);;
696                 prect->height = 1;
697                 prect++;
698                 (*piTop)++;
699
700                 prect->x = x;                   /* left end */
701                 prect->y = y+cheight-swidth+
702                                 ((wmGD.frameStyle == WmSLAB)? 0 : 1);
703                 prect->width = 1;
704                 prect->height = swidth-2+((wmGD.frameStyle == WmSLAB)? 1 : 0);
705                 (*piTop)++;
706
707                 if (((prBot->used + 4) > prBot->allocated) &&
708                     (!ExtendRList (prBot, (unsigned int) RLIST_EXTENSION_SIZE)))
709                 {
710                     return;
711                 }
712
713                 piBot = &(prBot->used);
714                 prect = &(prBot->prect[*piBot]); /* bottom shadow parts */
715
716
717                 prect->x = x+1;                 /* bottom - row 1 */
718                 prect->y = y+cheight-2;
719                 prect->width = cwidth-1;
720                 prect->height = 1;
721                 prect++;
722                 (*piBot)++;
723
724                 prect->x = x;                   /* bottom - row 2 */
725                 prect->y = y+cheight-1;
726                 prect->width = cwidth;
727                 prect->height = 1;
728                 prect++;
729                 (*piBot)++;
730
731                 prect->x = x+cwidth-2;          /* right  - column 1 */
732                 prect->y = y+1;
733                 prect->width = 1;
734                 prect->height = cheight-3;
735                 prect++;
736                 (*piBot)++;
737
738                 prect->x = x+cwidth-1;          /* right  - column 2 */
739                 prect->y = y;
740                 prect->width = 1;
741                 prect->height = cheight-2;
742                 (*piBot)++;
743
744                 break;
745
746         case STRETCH_SOUTH_WEST:
747                 if (((prTop->used + 4) > prTop->allocated) &&
748                     (!ExtendRList (prTop, (unsigned int) RLIST_EXTENSION_SIZE)))
749                 {
750                     return;
751                 }
752
753                 piTop = &(prTop->used);
754                 prect = &(prTop->prect[*piTop]);
755
756                 prect->x = x;                   /* top end */
757                 prect->y = y;
758                 prect->width = swidth;
759                 prect->height = 1;
760                 prect++;
761                 (*piTop)++;
762
763                 prect->x = x;                   /* left (col 1) */
764                 prect->y = y+1;
765                 prect->width = 1;
766                 prect->height = cheight-1;
767                 prect++;
768                 (*piTop)++;
769
770                 prect->x = x+1;                 /* left (col 2) */
771                 prect->y = y+1;
772                 prect->width = 1;
773                 prect->height = cheight-2;
774                 prect++;
775                 (*piTop)++;
776
777                 if (wmGD.frameStyle == WmRECESSED)
778                 {
779                     prect->x = x+swidth;                /* top inside (row 2) */
780                     prect->y = y+cheight-swidth;
781                     prect->width = cwidth-swidth;
782                     prect->height = 1;
783                     (*piTop)++;
784                 }
785
786                 if (((prBot->used + 4) > prBot->allocated) &&
787                     (!ExtendRList (prBot, (unsigned int) RLIST_EXTENSION_SIZE)))
788                 {
789                     return;
790                 }
791
792                 piBot = &(prBot->used);
793                 prect = &(prBot->prect[*piBot]); /* bottom shadow parts */
794
795
796                 if (wmGD.frameStyle == WmRECESSED)
797                 {
798                     prect->x = x+swidth-1;      /* right inside (col 2) */
799                     prect->y = y+1;
800                     prect->width = 1;
801                     prect->height = cheight-swidth;
802                     prect++;
803                     (*piBot)++;
804                 }
805
806                 prect->x = x+cwidth-1;          /* right end */
807                 prect->y = y+cheight-swidth+
808                                 ((wmGD.frameStyle == WmSLAB)? 0 : 1);
809                 prect->width = 1;
810                 prect->height = swidth-((wmGD.frameStyle == WmSLAB)? 0 : 1);
811                 prect++;
812                 (*piBot)++;
813
814                 prect->x = x+2;                 /* bottom (row 1) */
815                 prect->y = y+cheight-2;
816                 prect->width = cwidth-3;
817                 prect->height = 1;
818                 prect++;
819                 (*piBot)++;
820
821                 prect->x = x+1;                 /* bottom (row 2) */
822                 prect->y = y+cheight-1;
823                 prect->width = cwidth-2;
824                 prect->height = 1;
825                 (*piBot)++;
826
827                 break;
828     }
829 } /* END OF FUNCTION StretcherCorner */
830
831
832 \f
833 /*************************************<->*************************************
834  *
835  *  DrawStringInBox (dpy, win, gc, pbox, str)
836  *
837  *
838  *  Description:
839  *  -----------
840  *  Draws a null-terminated string inside the specified box (rectangle)
841  *
842  *
843  *  Inputs:
844  *  ------
845  *  dpy         - ptr to Display
846  *  win         - an X Window
847  *  gc          - graphics context to use
848  *  pfs         - pointer to XFontStruct for the font in "gc"
849  *  pbox        - ptr to XRectangle that encloses text
850  *  str         - String to write
851  * 
852  *  Outputs:
853  *  -------
854  *  none
855  *
856  *  Comments:
857  *  --------
858  *  o Assumes 8-bit text for now.
859  *  o Algorithm:  
860  *                      get length of String
861  *                      if String is short than box width then
862  *                          draw string centered in box
863  *                      otherwise
864  *                          draw string left justified and clipped to box
865  *  o The clip_x_origin, clip_y_origin, and clip_mask are reset to None
866  *    upon exit.
867  *  o Due to bugs and / or misunderstanding, I gave up on trying to 
868  *    extract the XFontStruct from the GC. I just made it a separate 
869  *    parameter.
870  *                      
871  *************************************<->***********************************/
872 void DrawStringInBox (Display *dpy, Window win, GC gc, XFontStruct *pfs, XRectangle *pbox, String str)
873 {
874     XGCValues gcv;
875     int textWidth;
876     int xCenter;
877     XRectangle clipBox;
878
879     /* compute text position */
880     textWidth = XTextWidth(pfs, str, strlen(str));
881
882     if (textWidth < (int) pbox->width) {        /* center text if there's room */
883         xCenter = (int) pbox->x + ((int) pbox->width - textWidth) / 2 ;
884         WmDrawString(dpy, win, gc, xCenter, (pbox->y + pfs->ascent), 
885                     str, strlen(str));
886     }
887     else {                              /* left justify & clip text */
888         clipBox.x = 0;                  /* set up clip rectangle */
889         clipBox.y = 0;
890         clipBox.width = pbox->width;
891         clipBox.height = pbox->height;
892
893         XSetClipRectangles (dpy, gc, pbox->x, pbox->y,  /* put into gc */
894                             &clipBox, 1, Unsorted);
895
896         WmDrawString(dpy, win, gc, pbox->x, (pbox->y + pfs->ascent), 
897                     str, strlen(str));
898
899         gcv.clip_x_origin = 0;          /* erase clip_mask from gc */
900         gcv.clip_y_origin = 0;
901         gcv.clip_mask = None;
902         XChangeGC (dpy, gc, 
903                    GCClipXOrigin | GCClipYOrigin | GCClipMask, &gcv);
904     }
905 } /* END OF FUNCTION DrawStringInBox */
906
907
908
909 \f
910 /*************************************<->*************************************
911  *
912  *  ExtendRList (prl, amt)
913  *
914  *
915  *  Description:
916  *  -----------
917  *  Extends the size of the RList
918  *
919  *
920  *  Inputs:
921  *  ------
922  *  prl         - ptr to Display
923  *  amt         - how much to extend it by
924  * 
925  *  Outputs:
926  *  -------
927  *  Returns True if succeeded, false otherwise.
928  *
929  *  Comments:
930  *  --------
931  *                      
932  *************************************<->***********************************/
933 Boolean ExtendRList (RList *prl, unsigned int amt)
934 {
935     unsigned int total, count;
936     XRectangle *pNewRect;
937     Boolean rval;
938
939
940     total = prl->allocated + amt;
941     if ( (pNewRect = (XRectangle *) XtMalloc (total * sizeof(XRectangle))) 
942          == NULL)
943     {
944         Warning (((char *)GETMESSAGE(28, 1, "Insufficient memory for graphics data")));
945         rval = False;
946     }
947     else 
948     {
949         prl->allocated = total;
950         rval = True;
951
952         if (prl->used != 0) {           /* copy from old structure */
953             count = prl->used * sizeof(XRectangle);
954             (void) memcpy ((void *)pNewRect, (void *)prl->prect, count);
955             if (prl->prect != NULL)
956                 XtFree ((char *)prl->prect);
957             prl->prect = pNewRect;
958         }
959     }
960     return (rval);
961 } /* END OF FUNCTION ExtendRList */
962
963
964 \f
965 /*************************************<->*************************************
966  *
967  *  AllocateRList (amt)
968  *
969  *
970  *  Description:
971  *  -----------
972  *  Allocates an RList of size "amt"
973  *
974  *
975  *  Inputs:
976  *  ------
977  *  amt         - number of XRectangles to allocate in list
978  * 
979  *  Outputs:
980  *  -------
981  *  Returns ptr to new RList structure if success, returns NULL ptr otherwise
982  *
983  *  Comments:
984  *  --------
985  *                      
986  *************************************<->***********************************/
987 RList *AllocateRList (unsigned int amt)
988 {
989     RList *prl;
990
991
992     if ((prl = (RList *) XtMalloc (sizeof (RList))) != NULL) 
993     {
994         if ( (prl->prect = (XRectangle *) XtMalloc (amt * sizeof(XRectangle))) 
995              == NULL)
996         {
997             XtFree ((char *)prl);
998             prl = NULL;
999         }
1000         else 
1001         {
1002             prl->allocated = amt;
1003             prl->used = 0;
1004
1005         }
1006     }
1007
1008     return (prl);
1009 } /* END OF FUNCTION AllocateRList */
1010
1011
1012 \f
1013 /*************************************<->*************************************
1014  *
1015  *  FreeRList (prl)
1016  *
1017  *
1018  *  Description:
1019  *  -----------
1020  *  Frees an RList
1021  *
1022  *
1023  *  Inputs:
1024  *  ------
1025  *  prl         - ptr to RList to free
1026  * 
1027  *  Outputs:
1028  *  -------
1029  *
1030  *  Comments:
1031  *  --------
1032  *                      
1033  *************************************<->***********************************/
1034 void FreeRList (RList *prl)
1035 {
1036     if (prl) 
1037     {
1038         if (prl->prect) 
1039             XtFree ((char *)prl->prect);
1040
1041         XtFree ((char *)prl);
1042     }
1043 }/* END OF FUNCTION FreeRList */
1044
1045 \f
1046 /*************************************<->*************************************
1047  *
1048  *  WmDrawString
1049  *
1050  *
1051  *  Description:
1052  *  -----------
1053  *  Draws a string
1054  *
1055  *
1056  *  Inputs:
1057  *  ------
1058  *  (same parameters used by XDrawString and XDrawImageString)
1059  * 
1060  *  Outputs:
1061  *  -------
1062  *
1063  *  Comments:
1064  *  --------
1065  *  o If wmGD.cleanText is True, then the text is drawn using 
1066  *    XDrawImageString. This provides some clean space around the text
1067  *    if the background area is stippled -- especially useful on 
1068  *    B/W displays.
1069  *                      
1070  *************************************<->***********************************/
1071 void WmDrawString (Display *dpy, Drawable d, GC gc, int x, int y, char *string, unsigned int length)
1072 {
1073     if (ACTIVE_PSD->cleanText)
1074     {
1075         XDrawImageString(dpy, d, gc, x, y, string, length);
1076     }
1077     else
1078     {
1079         XDrawString(dpy, d, gc, x, y, string, length);
1080     }
1081
1082 }/* END OF FUNCTION WmDrawString */
1083
1084
1085 \f
1086 /*************************************<->*************************************
1087  *
1088  *  WmXmDrawString
1089  *
1090  *
1091  *  Description:
1092  *  -----------
1093  *  Draws a string
1094  *
1095  *
1096  *  Inputs:
1097  *  ------
1098  *  (subset of parameters used by XmStringDraw and XmStringDrawImage)
1099  * 
1100  *  Outputs:
1101  *  -------
1102  *
1103  *  Comments:
1104  *  --------
1105  *  o If wmGD.cleanText is True, then the text is drawn using 
1106  *    XmStringDrawImage. This provides some clean space around the text
1107  *    if the background area is stippled -- especially useful on 
1108  *    B/W displays.
1109  *                      
1110  *************************************<->***********************************/
1111 void WmDrawXmString (Display *dpy, Window w, XmFontList xmfontlist, 
1112                      XmString xmstring, GC gc, Position x, Position y, 
1113                      Dimension width,  XRectangle *pbox, Boolean bCenter)
1114 {
1115     Dimension textWidth;
1116     int alignment;
1117     
1118
1119     textWidth = XmStringWidth(xmfontlist, xmstring);
1120
1121     alignment = bCenter ? XmALIGNMENT_CENTER : XmALIGNMENT_BEGINNING;
1122
1123     if (textWidth >= pbox->width)  /* can't center text if no room */
1124     {                              /* left justify & clip text */
1125         alignment = XmALIGNMENT_BEGINNING;
1126     }
1127     
1128     if (ACTIVE_PSD->cleanText)
1129     {
1130         XmStringDrawImage(dpy, w, xmfontlist, xmstring, gc, x, y, width, 
1131                           alignment, XmSTRING_DIRECTION_L_TO_R, 
1132                           pbox);
1133     }
1134     else
1135     {
1136         XmStringDraw (dpy, w, xmfontlist, xmstring, gc, x, y, width, 
1137                       alignment, XmSTRING_DIRECTION_L_TO_R, pbox);
1138     }
1139 } /* END OF FUNCTION WmDrawXmString */
1140
1141 /*************************************<->*************************************
1142  *
1143  *  WmInstallBitmapIntoXmCache (pchName, bitmap, width, height)
1144  *
1145  *
1146  *  Description:
1147  *  -----------
1148  *  Installs all or part of a pixmap into the Xm cache. This pixmap
1149  *  may be retrieved later by a call to XmGetPixmap.
1150  *
1151  *  Inputs:
1152  *  ------
1153  *  pchName     = pointer to name of bitmap 
1154  *  bitmap      = depth-1 pixmap
1155  *  width       = width of portion to install
1156  *  height      = height of portion to install
1157  * 
1158  *  Outputs:
1159  *  -------
1160  *  none
1161  *
1162  *  Comments:
1163  *  --------
1164  *  This always installs the Northwest corner of the passed in bitmap.
1165  *  If the width and height match the size of the bitmap, then the
1166  *  whole thing is installed in the cache.
1167  *                      
1168  *************************************<->***********************************/
1169 void WmInstallBitmapIntoXmCache (unsigned char *pchName,
1170     Pixmap bitmap, unsigned int width, unsigned int height)
1171 {
1172     XImage *pImage;
1173
1174     pImage = XGetImage (DISPLAY, bitmap, 0, 0, width, height, 1L, XYBitmap);
1175
1176     XmInstallImage (pImage, (char *)pchName);
1177 } /* END OF FUNCTION WmInstallBitmapIntoXmCache */
1178
1179
1180 \f
1181 /*************************************<->*************************************
1182  *
1183  *  WmInstallBitmapDataIntoXmCache (pSD, pchName, pData)
1184  *
1185  *
1186  *  Description:
1187  *  -----------
1188  *  Installs built-in bitmap data into the Xm Pixmap cache. The image
1189  *  may be retrieved later by a call to XmGetPixmap.
1190  *
1191  *  Inputs:
1192  *  ------
1193  *  pSD         = pointer to screen data
1194  *  pchName     = pointer to name of bitmap 
1195  *  pData       = pointer to the bitmap data
1196  * 
1197  *  Outputs:
1198  *  -------
1199  *  none
1200  *
1201  *  Comments:
1202  *  --------
1203  *  This is principally for putting built-in pixmap data into the Xm
1204  *  cache to allow for uniform access to pixmap creation.
1205  *
1206  *  ***WARNING***
1207  *  Do NOT call XmDestroyPixmap on images cached via this routine unless
1208  *  pData passed in points to malloc'ed memory. XmDestroyPixmap could 
1209  *  try to free this data.
1210  *                      
1211  *************************************<->***********************************/
1212 void WmInstallBitmapDataIntoXmCache (WmScreenData *pSD, 
1213     unsigned char *pchName, char *pData, unsigned int width,
1214     unsigned int height)
1215 {
1216     XImage *pImage;
1217
1218     if ((pImage = (XImage *) XtMalloc (sizeof (XImage))))
1219     {
1220         pImage->width = width; 
1221         pImage->height = height;
1222         pImage->xoffset = 0;
1223         pImage->data = pData;
1224         pImage->format = XYBitmap;
1225         pImage->byte_order = MSBFirst;
1226         pImage->bitmap_pad = 8;
1227         pImage->bitmap_bit_order = LSBFirst;
1228         pImage->bitmap_unit = 8;
1229         pImage->depth = 1;
1230         pImage->bytes_per_line = (width/8) + ((width%8) != 0 ? 1 : 0);
1231         pImage->obdata = NULL;
1232
1233         XmInstallImage(pImage, (char *)pchName);
1234     }
1235
1236 } /* END OF FUNCTION WmInstallBitmapDataIntoXmCache */