dtcm: Resolve CID 87562
[oweals/cde.git] / cde / programs / dtcm / dtcm / icon.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 librararies 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 /* $TOG: icon.c /main/5 1998/01/09 15:29:53 cshi $ */
24 /*
25  *  (c) Copyright 1993, 1994 Hewlett-Packard Company
26  *  (c) Copyright 1993, 1994 International Business Machines Corp.
27  *  (c) Copyright 1993, 1994 Novell, Inc.
28  *  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
29  */
30
31 #define   NO_RES_DISPLAY        0
32 #define   LOW_RES_DISPLAY       1
33 #define   VGA_RES_DISPLAY       2
34 #define   MED_RES_DISPLAY       3
35 #define   HIGH_RES_DISPLAY      4
36
37 #define  DTCM_STD_ICON  "IcCM"
38 #define  DTCM_INV_ICON  "IcCMinv"
39
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <Xm/Xm.h>
43 #include "calendar.h"
44
45 /* XXX: Defined in Xm/IconFile.h but the file isn't installed??? */ 
46 /*
47  * values for icon magnitude
48  */
49 #define XmUNSPECIFIED_ICON_SIZE 0
50 #define XmLARGE_ICON_SIZE       1
51 #define XmMEDIUM_ICON_SIZE      2
52 #define XmSMALL_ICON_SIZE       3
53 #define XmTINY_ICON_SIZE        4
54 extern String XmGetIconFileName( 
55                         Screen *screen,
56                         String imageInstanceName,
57                         String imageClassName,
58                         String hostPrefix,
59                         unsigned int size) ;
60
61 /* XXX: Private routines, but what are my other choices? */
62 extern Pixmap _DtGetMask(Screen *screen, char *image_name);
63 extern int _DtGetDisplayResolution(Display *disp, int screen);
64
65 static Boolean load_icon(Calendar *c, IconInfo  *icon, char *icon_name, int size, Pixel, Pixel);
66
67 static int
68 wm_icon_preference(
69         Display         *dpy,
70         Screen          *screen,
71         int              size)
72 {
73         int              icon_size_count,
74                          cal_icon_size,
75                          i;
76         XIconSize       *icon_sizes;
77
78         if (XGetIconSizes(dpy, XRootWindowOfScreen(screen),
79                           &icon_sizes, &icon_size_count) == 0)
80                 return (size);
81
82         /* Calendar icons are either 32x32 or 48x48 */
83         if (size == XmLARGE_ICON_SIZE)
84                 cal_icon_size = 48;
85         else
86                 cal_icon_size = 32;
87
88         for (i = 0; i < icon_size_count; i++) {
89                 if (icon_sizes[i].min_width <= cal_icon_size &&
90                     icon_sizes[i].max_width >= cal_icon_size &&
91                     icon_sizes[i].min_height <= cal_icon_size &&
92                     icon_sizes[i].max_height >= cal_icon_size) {
93
94                         XFree(icon_sizes);
95                         return (size);
96                 }
97         }
98         /* If we are here then WM doesn't want us to use this icon
99          * size.  If we are using 48x48 then we can see if 32x32 will
100          * work.
101          */
102         if (size == XmLARGE_ICON_SIZE)
103                 cal_icon_size = 32;
104
105         for (i = 0; i < icon_size_count; i++) {
106                 if (icon_sizes[i].min_width <= cal_icon_size &&
107                     icon_sizes[i].max_width >= cal_icon_size &&
108                     icon_sizes[i].min_height <= cal_icon_size &&
109                     icon_sizes[i].max_height >= cal_icon_size) {
110
111                         XFree(icon_sizes);
112                         return (XmMEDIUM_ICON_SIZE);
113                 }
114         }
115         XFree(icon_sizes);
116         return (0);
117 }
118
119 /*
120  * We load two icons.  The main icon used when the tool is iconic and an
121  * inverted icon that is used during flashing when a reminder occurs.
122  */
123
124 static Boolean
125 load_icons(
126         Calendar        *c)
127 {
128         Pixel            fg, bg;
129         int              resolution,
130                          size;
131         Screen          *screen = XtScreen(c->frame);
132
133         if (!c->icon)
134                 c->icon = (IconInfo *) ckalloc(sizeof(IconInfo));
135         if (!c->icon_inverted)
136                 c->icon_inverted = (IconInfo *) ckalloc(sizeof(IconInfo));
137
138         XtVaGetValues(c->canvas, 
139                         XmNforeground,  &fg, 
140                         XmNbackground,  &bg,
141                         NULL);
142
143         resolution = _DtGetDisplayResolution(XtDisplay(c->frame), 
144                                 XScreenNumberOfScreen(screen));
145
146         /*
147          * The CDE spec says we use a large icon in high and medium
148          * resolution.  We use a medium size icon in low res.
149          */
150         switch (resolution) {
151             case HIGH_RES_DISPLAY:
152             case MED_RES_DISPLAY:
153                 size = XmLARGE_ICON_SIZE;
154                 break;
155             case LOW_RES_DISPLAY:
156             default:
157                 size = XmMEDIUM_ICON_SIZE;
158                 break;
159         }
160
161         /* See if the resolution size we have chosen is acceptable by the WM */
162         if (!(size = wm_icon_preference(XtDisplay(c->frame), screen, size))) {
163                 c->icon->icon = 0;
164                 c->icon_inverted->icon = 0;
165                 return (FALSE);
166         }
167
168         if (!load_icon(c, c->icon, DTCM_STD_ICON, size, fg, bg))
169                 return (FALSE);
170
171         /* 
172          * If we are color we load a color icon that has been inverted
173          * by a graphic's artist.  If we are mono or reduced color we take 
174          * our one bit deep pixmap and invert it ourself by switching fg and
175          * bg.
176          */
177         if (c->icon->icon_depth >= 8) {
178                 if (!load_icon(c, c->icon_inverted, DTCM_INV_ICON, size, 
179                                fg, bg))
180                         return (FALSE);
181         } else {
182                 /* Reverse fg/bg on STD_ICON to get inverted icon. */
183                 /* XXX: This probably won't work on 1 < depth < 8 visuals */
184                 if (!load_icon(c, c->icon_inverted, DTCM_STD_ICON, size, 
185                                bg, fg))
186                         return (FALSE);
187         }
188         return (TRUE);
189 }
190
191 static Boolean
192 load_icon(
193         Calendar        *c,
194         IconInfo        *icon,
195         char            *icon_name,
196         int              size,
197         Pixel            fg,
198         Pixel            bg)
199 {
200         char            *icon_filename;
201         int              x, y;
202         Window           root;
203         unsigned int     border_width;
204         Screen          *screen = XtScreen(c->frame);
205
206         if (!(icon_filename = XmGetIconFileName(screen, NULL, icon_name, 
207                                                                 NULL, size))) {
208                 icon->icon = 0;
209                 return (FALSE);
210         }
211
212         if ((icon->icon = XmGetPixmap(screen, icon_filename, fg, bg)) ==
213                                                         XmUNSPECIFIED_PIXMAP) {
214                 free(icon_filename);
215                 icon->icon = 0;
216                 return (FALSE);
217         }
218
219         if ((icon->icon_mask = _DtGetMask(screen, icon_filename)) ==
220                                                         XmUNSPECIFIED_PIXMAP) {
221                 free(icon_filename);
222                 icon->icon = 0;
223                 icon->icon_mask = 0;
224                 return (FALSE);
225         }
226
227         /* Store away the size of the icon */
228         XGetGeometry(XtDisplay(c->frame),
229                      icon->icon,
230                      &root,
231                      &x, &y,
232                      &icon->icon_width, &icon->icon_height,
233                      &border_width, &icon->icon_depth);
234
235         XtFree(icon_filename);
236         return (TRUE);
237 }
238
239 static void
240 free_icon(
241         Calendar        *c,
242         IconInfo        *icon)
243 {
244         if (!icon)
245                 return;
246
247         if (icon->icon)
248                 XmDestroyPixmap(XtScreen(c->frame), icon->icon);
249
250         icon->icon = 0;
251
252         if (icon->icon_mask)
253                 XmDestroyPixmap(XtScreen(c->frame), icon->icon_mask);
254
255         icon->icon_mask = 0;
256 }
257
258 static void
259 paint_icon_date(
260         Calendar        *c)
261 {
262         Tick             current_time;
263         char             buf[25];
264         Cal_Font        *font = c->fonts->iconfont;
265         new_XContext    *xc;
266         int              len, 
267                          x, y, 
268                          width, height, 
269                          nop;
270         Screen          *s = XtScreen(c->canvas);
271         Pixel            fg, bg;
272         GC               gc;
273         XGCValues        gc_vals;
274         Display         *dpy;
275
276         if (!(c->icon && c->icon->icon && c->icon->icon_mask))
277                 return;
278
279         dpy = XtDisplayOfObject(c->frame);
280
281         current_time = now();
282         XtVaSetValues(c->frame, XmNiconName, months[month(current_time)], NULL);
283         xc = c->xcontext;
284
285         if (c->icon->icon_depth == 1) {
286                 XtVaGetValues(c->canvas, 
287                         XmNforeground,  &fg, 
288                         XmNbackground,  &bg,
289                         NULL);
290         } else {
291                 fg = BlackPixelOfScreen(s);
292                 bg = WhitePixelOfScreen(s);
293         }
294
295         gc_vals.foreground = fg;
296         gc_vals.function = GXcopy;
297         gc_vals.fill_style = FillSolid;
298         gc = XCreateGC(xc->display, c->icon->icon, GCForeground | GCFunction |
299                                                    GCFillStyle, &gc_vals);
300
301         /* painting new date */
302         /* day of the month */
303         (void) sprintf(buf, "%d", dom(current_time));
304         len = cm_strlen(buf);
305         CalTextExtents(font, buf, len, &nop, &nop, &width, &height);
306         x = c->icon->icon_width/2 - width/2 - 1;
307         y = c->icon->icon_height - 2 * (c->icon->icon_height - height) / 3;
308
309         CalDrawString(dpy, c->icon->icon, font, gc, x, y, buf, len);
310
311         gc_vals.foreground = bg;
312         XChangeGC(xc->display, gc, GCForeground, &gc_vals);
313         if (c->icon_inverted && c->icon_inverted->icon 
314                              && c->icon_inverted->icon_mask)
315                 CalDrawString(dpy, c->icon_inverted->icon, font, 
316                                    gc, x, y, buf, len);
317
318         XFreeGC(xc->display, gc);
319         XFlush(xc->display);
320 }
321  
322 void
323 paint_icon(Calendar *c)
324 {
325
326         /* Free the old pixmaps since they have the wrong date in them. */
327         if (c->icon && c->icon->icon)
328                 free_icon(c, c->icon);
329         if (c->icon_inverted && c->icon_inverted->icon)
330                 free_icon(c, c->icon_inverted);
331
332         /* Load the icon, mask and related info into calendar->icon */
333         load_icons(calendar);
334
335         paint_icon_date(c);
336
337         XtVaSetValues(c->frame, XmNiconPixmap, NULL, NULL);
338
339         if (c->icon && c->icon->icon && c->icon->icon_mask)
340                 XtVaSetValues(c->frame, 
341                         XmNiconPixmap, c->icon->icon,
342                         XmNiconMask, c->icon->icon_mask,
343                         NULL);
344 }