dtcm: Resolve CID 87562
[oweals/cde.git] / cde / programs / dtcm / dtcm / graphics.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 /*******************************************************************************
24 **
25 **  graphics.c
26 **
27 **  $XConsortium: graphics.c /main/3 1995/11/03 10:27:52 rswiston $
28 **
29 **  RESTRICTED CONFIDENTIAL INFORMATION:
30 **
31 **  The information in this document is subject to special
32 **  restrictions in a confidential disclosure agreement between
33 **  HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34 **  document outside HP, IBM, Sun, USL, SCO, or Univel without
35 **  Sun's specific written approval.  This document and all copies
36 **  and derivative works thereof must be returned or destroyed at
37 **  Sun's request.
38 **
39 **  Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40 **
41 *******************************************************************************/
42
43 /*                                                                      *
44  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
45  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
46  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
47  * (c) Copyright 1993, 1994 Novell, Inc.                                *
48  */
49
50 #ifndef lint
51 static  char sccsid[] = "@(#)graphics.c 1.23 94/11/29 Copyr 1994 Sun Microsystems, Inc.";
52 #endif
53
54 #include <EUSCompat.h>
55 #include <stdio.h>
56 #include <sys/stat.h>
57 #if !defined(CSRG_BASED)
58 #include <sys/sysmacros.h>
59 #endif
60 #include <sys/param.h> /* MAXPATHLEN defined here */
61 #ifdef SVR4
62 #include <sys/utsname.h> /* SYS_NMLN */
63 #endif /* SVR4 */
64 #include <limits.h>
65 #include <dirent.h>
66 #include <ctype.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <sys/time.h>
70 #include <rpc/rpc.h>
71 #include <sys/resource.h>
72 #include <sys/wait.h>
73 #include <netinet/in.h>
74 #include <X11/Xlib.h>
75 #include <Xm/DrawingA.h>
76 #include <Xm/PushB.h>
77 #include <Xm/RowColumn.h>
78 #include <Xm/ManagerP.h>
79 #include <Xm/GadgetP.h>
80 #include "util.h"
81 #include "misc.h"
82 #include "timeops.h"
83 #include "datefield.h"
84 #include "props.h"
85 #include "props_pu.h"
86 /*
87 #include "select.h"
88 */
89 /*
90 #include "editor.h"
91 #include "graphics.h"
92 */
93 #include "browser.h"
94 #include "blist.h"
95 /*
96 #include "alarm.h"
97 #include "dayglance.h"
98 #include "yearglance.h"
99 #include "weekglance.h"
100 */
101 #include "calendar.h"
102 /*
103 #include "todo.h"
104 */
105 #include "find.h"
106 #include "goto.h"
107 #include "tempbr.h"
108 /*
109 #include "gettext.h"
110 #include "namesvc.h"
111 #include "monthglance.h"
112 */
113
114 #define gray_data_75_width      8
115 #define gray_data_75_height     8
116 #define gray_data_50_width      8
117 #define gray_data_50_height     8
118 #define gray_data_25_width      8
119 #define gray_data_25_height     8
120 #define black_data_width        8
121 #define black_data_height       8
122
123 #define solid_list_length               2
124 #define short_dotted_list_length        2
125 #define dotted_list_length              2
126 #define dot_dashed_list_length          4
127 #define short_dashed_list_length        2
128 #define long_dashed_list_length         2
129 #define odd_dashed_list_length          3
130 static unsigned char black_data[] = {
131         0xFF,
132         0xFF,
133         0xFF,
134         0xFF,
135         0xFF,
136         0xFF,
137         0xFF,
138         0xFF
139 };
140 static unsigned char gray_data_75[] = {
141         0xDD,
142         0xBB,
143         0xEE,
144         0xF7,
145         0xDD,
146         0xBB,
147         0xEE,
148         0xF7
149 };
150
151 static unsigned char gray_data_50[] = {
152         0xAA,
153         0x55,
154         0xAA,
155         0x55,
156         0xAA,
157         0x55,
158         0xAA,
159         0x55
160 };
161
162 static unsigned char gray_data_25[] = {
163         0x88,
164         0x22,
165         0x44,
166         0x11,
167         0x88,
168         0x22,
169         0x44,
170         0x11
171 };
172
173 static Pixmap black_data_pixmap = NULL;
174 static Pixmap gray_data_75_pixmap = NULL;
175 static Pixmap gray_data_50_pixmap = NULL;
176 static Pixmap gray_data_25_pixmap = NULL;
177  
178 static unsigned char solid[solid_list_length] = {1, 0};
179 static unsigned char short_dotted[short_dotted_list_length] = {1, 1};
180 static unsigned char dotted[dotted_list_length] = {3, 1};
181 static unsigned char dot_dashed[dot_dashed_list_length] = {3, 4, 3, 1};
182 static unsigned char short_dashed[short_dashed_list_length] = {4, 4};
183 static unsigned char long_dashed[long_dashed_list_length] = {4, 7};
184 static unsigned char odd_dashed[odd_dashed_list_length] = {1, 2, 3};
185
186 static unsigned char *dash_list[] = {
187         solid,
188         short_dotted,
189         dotted,
190         dot_dashed,
191         short_dashed,
192         long_dashed,
193         odd_dashed,
194 };
195
196 extern void
197 gr_clear_area(new_XContext *xc, int x, int y, Dimension w, Dimension h) {
198
199         XFillRectangle(xc->display, xc->xid, xc->clear_gc, x, y, w, h);
200 /*
201         XClearArea(xc->display, xc->xid, x, y, w, h, False);
202 */
203 }
204
205 extern void
206 gr_clear_box (new_XContext *xc, int x, int y, int w, int h) {
207
208         x+=1; y+=1; w-=1; h-=1;
209
210         XFillRectangle(xc->display, xc->xid, xc->clear_gc, x, y, w, h);
211 /*
212         XClearArea(xc->display, xc->xid, x, y, w, h, False);
213 */
214 }
215
216 extern void
217 gr_make_grayshade(new_XContext *xc, int x, int y, int w, int h, int shade) {
218
219         XColor colorcell_del, rgb_db_ref;
220  
221         XSetForeground((Display*)xc->display, (GC)xc->gc, (unsigned long)xc->colorcell_del[shade].pixel);
222  
223         XSetFillStyle(xc->display, xc->gc, FillSolid);
224         XFillRectangle(xc->display, xc->xid, xc->gc, x, y, w, h);
225 }
226
227 extern void
228 gr_make_gray(new_XContext *xc, int x, int y, int w, int h, int percent) {
229
230         /* Set up gray stipple */
231         switch(percent) {
232         case 25:
233                 XSetStipple(xc->display, xc->gc, gray_data_25_pixmap);
234                 break;
235         case 50:
236                 XSetStipple(xc->display, xc->gc, gray_data_50_pixmap);
237                 break;
238         case 75:
239                 XSetStipple(xc->display, xc->gc, gray_data_75_pixmap);
240                 break;
241         default:
242                 XSetStipple(xc->display, xc->gc, gray_data_25_pixmap);
243                 break;
244         }
245  
246         XSetForeground(xc->display, xc->gc, xc->foreground);
247         XSetFillStyle(xc->display, xc->gc, FillOpaqueStippled);
248         XFillRectangle(xc->display, xc->xid, xc->gc, x, y, w, h);
249 }
250
251 extern void
252 gr_make_rgbcolor(new_XContext *xc, Colormap cms, int x, int y, int w, int h, 
253                  int r, int g, int b) {
254
255         XColor colorcell_del;
256
257         colorcell_del.red = (unsigned short)(r<<8);
258         colorcell_del.green = (unsigned short)(g<<8);
259         colorcell_del.blue = (unsigned short)(b<<8);
260         XAllocColor(xc->display, cms, &colorcell_del);
261
262         XSetForeground((Display*)xc->display, (GC)xc->gc,
263                        (unsigned long)colorcell_del.pixel);
264         XSetFillStyle(xc->display, xc->gc, FillSolid);
265         XFillRectangle(xc->display, xc->xid, xc->gc, x, y, w, h);
266 }
267
268 extern int
269 gr_nchars(int area, char *str, Cal_Font *font) {
270
271         char *buf;
272         int i, l, w=0, n=0;
273         int first = 1;
274         int len = cm_strlen(str);
275         int nop, width;
276
277         CalTextExtents(font, str, len, &nop, &nop, &width, &nop);
278         if (width <= area)
279                 return(strlen(str));
280
281         for (i=0; i<len; i++) {
282                 if ( first ) {
283                         buf = (char *)cm_mbchar(str);
284                         first = 0;
285                 } else {
286                         buf = (char *)cm_mbchar((char *)NULL);
287                 }
288                 l = cm_strlen(buf);
289                 CalTextExtents(font, buf, l, &nop, &nop, &width, &nop);
290                 w += width;
291                 if (w <= area)
292                         n += mblen(buf, MB_LEN_MAX);
293                 else break;
294         }
295         return(n);
296 }
297
298 void
299 gr_draw_rgb_box(
300         new_XContext    *xc,
301         int             x,
302         int             y,
303         int             w,
304         int             h,
305         int             thickness,
306         int             shade,
307         Colormap        cms)
308
309 {
310         XColor colorcell_del, rgb_db_ref;
311         unsigned long pixel;
312         int     gc_changed = 0;
313
314         switch(shade) {
315                 case RED:
316                         /*
317                         XGetGCValues(xc->display, xc->gc,
318                         GCForeground|GCFillStyle, xc->gcvals);
319                         */
320                         pixel = xc->colorcell_del[RED].pixel;
321                 break;
322                 default:
323                         pixel = shade;
324                 break;
325         }
326
327         XSetForeground((Display*)xc->display, (GC)xc->gc, pixel);
328         XSetFillStyle(xc->display, xc->gc, FillSolid);
329
330         for (;thickness > 0; thickness--) {
331                 XDrawRectangle(xc->display, xc->xid, xc->gc, x, y, w, h);
332                 x++; y++;
333                 w -= 2; h -=2;
334         }
335
336         return;
337 }
338
339 void
340 gr_dissolve_box(
341         new_XContext    *xc,
342         int             x,
343         int             y,
344         int             w,
345         int             h,
346         int             thickness)
347 {
348         for (;thickness > 0; thickness--) {
349                 XDrawRectangle(xc->display, xc->xid, xc->clear_gc, x, y, w, h);
350                 x++; y++;
351                 w -= 2; h -=2;
352         }
353 }
354
355 /*  given an area of a certain length (in pixels), compute
356     where to lay down a string such that it's centered */
357  
358 extern int
359 gr_center(int area, char *str, Cal_Font *font) {
360
361         int i, strl, l, w, first = 1;
362         int nop, width;
363         char *buf;
364
365         w = 0;
366         strl = cm_strlen(str);
367         for (i=0; i<strl; i++) {
368                 if ( first ) {
369                         buf = (char*)cm_mbchar(str);
370                         first = 0;
371                 } else {
372                         buf = (char*)cm_mbchar((char *)NULL);
373                 }
374                 l = cm_strlen(buf);
375                 CalTextExtents(font, buf, l, &nop, &nop, &width, &nop);
376                 w += width;
377         }
378         return ((area - w)/2);
379 }        
380
381 extern void
382 gr_text(new_XContext *xc, int x, int y, Cal_Font *font, char *str, 
383         XRectangle *rect) {
384  
385         int len = cm_strlen(str);
386         int x2, y2, w, h;
387         XRectangle overall_ink_return;
388  
389         if (rect != NULL) {
390                 CalTextExtents(font, str, len, &x2, &y2, &w, &h);
391
392                 overall_ink_return.x = x2 + rect->x;
393                 overall_ink_return.y = y2 + rect->y;
394                 overall_ink_return.width = w;
395                 overall_ink_return.height = h;
396
397                 if (!myrect_intersectsrect(rect, &overall_ink_return))
398                         return;
399         }
400         CalDrawString(xc->display, xc->xid, font, xc->draw_gc, x, y,
401                       str, cm_strlen(str));
402 }
403  
404 extern void
405 gr_text_rgb(new_XContext *xc, int x, int y, Cal_Font *font, char *str, 
406             Pixel shade, Colormap cms, XRectangle *rect) {
407
408         XRectangle overall_ink_return;
409         int x2, y2, w, h;
410  
411         if (rect != NULL) {
412                 CalTextExtents(font, str, cm_strlen(str), &x2, &y2, &w, &h);
413
414                 overall_ink_return.x = x2 + rect->x;
415                 overall_ink_return.y = y2 + rect->y;
416                 overall_ink_return.width = w;
417                 overall_ink_return.height = h;
418
419                 if (!myrect_intersectsrect(rect, &overall_ink_return))
420                         return;
421         }
422
423         XSetForeground((Display*)xc->display, (GC)xc->gc,
424                         (unsigned long)shade);
425
426         CalDrawString(xc->display, xc->xid, font, xc->gc, x, y, 
427                         str, cm_strlen(str));
428 }
429
430 extern void 
431 gr_draw_line(new_XContext *xc, int x1, int y1, int x2, int y2, 
432              GR_Line_Style style, XRectangle *rect) {
433
434         int dash_offset = 0;
435
436         if (rect != NULL) {
437                 XRectangle    gr_rect;
438
439                 gr_rect.x = x1;
440                 gr_rect.y = y1;
441                 gr_rect.width = x2-x1;
442                 gr_rect.height = y2-y1;
443
444                 if (!myrect_intersectsrect(rect, &gr_rect))
445                         return;
446         }
447         if (style==gr_solid) {
448                 XDrawLine(xc->display, xc->xid, xc->draw_gc, x1, y1, x2,
449 y2);
450         }
451         else {
452                 /* Set up and paint */
453                 XSetForeground(xc->display, xc->gc, xc->foreground);
454                 XSetDashes(xc->display, xc->gc, dash_offset,
455                         (char *)dash_list[style],
456                         short_dotted_list_length);
457                 XSetLineAttributes(xc->display, xc->gc, 0,
458                         LineOnOffDash, CapNotLast, JoinMiter);
459                 XDrawLine(xc->display, xc->xid, xc->gc, x1, y1, x2, y2);
460         }
461  
462 }
463
464 extern void 
465 gr_draw_box(new_XContext *xc, int x, int y, int w, int h, XRectangle *rect) {
466
467         if (rect != NULL) {
468                 XRectangle    gr_rect;
469  
470                 gr_rect.x = x;
471                 gr_rect.y = y;
472                 gr_rect.width = w;
473                 gr_rect.height = h;
474
475                 if (!myrect_intersectsrect(rect, &gr_rect))
476                         return;
477         }
478         XDrawRectangle(xc->display, xc->xid, xc->draw_gc, x, y, w, h);
479 }        
480
481 extern void 
482 gr_draw_glyph(new_XContext *src_xc, new_XContext *dst_xc, Pixmap pixmap, 
483               int x, int y, int w, int h) {
484
485         XSetStipple(src_xc->display, src_xc->gc, pixmap);
486         XSetTSOrigin(src_xc->display, src_xc->gc, x, y);
487         XFillRectangle(src_xc->display, dst_xc->xid, src_xc->gc, x, y, w, h);
488 }
489  
490 static void
491 saturate(XColor *xclr)
492
493 {
494         unsigned short n;
495
496         n = MAX(xclr->red, xclr->green);
497         n = MAX(n, xclr->blue);
498
499         n = USHRT_MAX - n;
500
501         xclr->red += n;
502         xclr->blue += n;
503         xclr->green += n;
504
505         return;
506 }
507  
508 /*
509  * Allocate and initialize an XContext
510  */
511 new_XContext *
512 gr_create_xcontext(Calendar *c, Widget widget, GR_depth depth, XtAppContext app)
513 {
514
515         new_XContext    *xc;
516         Colormap        cms = NULL;
517         XGCValues       gc_vals, tmp_vals;
518         GC              hilight_gc;
519         XColor          exact_color;
520         XColor          def_color;
521  
522         /* X Drawing Stuff */
523         if ((xc = (new_XContext *) ckalloc(sizeof(new_XContext))) == NULL)
524                 return NULL;
525  
526         xc->display = (Display *) XtDisplay(widget);
527         xc->app = app;
528  
529         if (depth == gr_mono) {
530                 xc->foreground = 1;
531                 xc->background = 0;
532                 xc->hilight_color = 1;
533         } else {
534                 XtVaGetValues(widget,
535                         XmNbackground, &xc->background,
536                         XmNforeground, &xc->foreground,
537                         NULL);
538                 /*
539                  * XXX EEEEEEK!  We use a private interface to get the
540                  * hilight color.  We do this because there is no public
541                  * interface.
542                  */
543                 hilight_gc = XmParentHighlightGC(widget);
544                 XGetGCValues(xc->display, hilight_gc, GCForeground, &tmp_vals);
545                 xc->hilight_color = tmp_vals.foreground;
546         }
547  
548         xc->xid = XtWindowOfObject(widget);
549         xc->screen_depth = DefaultDepthOfScreen(XtScreen(widget));
550
551         /*                                                      
552          * Create general purpose gc.  This gc is changed as needed by
553          * the drawing routines.
554          */
555         xc->gcvals = (XGCValues *) ckalloc(sizeof(XGCValues));
556         xc->gcvals->foreground = xc->foreground;
557         xc->gcvals->background = xc->background;
558
559         xc->gcvals->fill_style = FillOpaqueStippled;
560         xc->gc = XCreateGC(
561                 xc->display,
562                 xc->xid,
563                 GCForeground|GCBackground|GCFillStyle,
564                 xc->gcvals);
565
566         /*
567          * Specialized GCs. We create a couple of specialized GCs to increase   
568          * the speed of common operations.  This way we don't need to change
569          * the GC for every operation.
570          */
571
572         /* GC used for clearing */
573         gc_vals.foreground = xc->background;
574         xc->clear_gc = XCreateGC(xc->display, xc->xid, GCForeground, &gc_vals);
575         
576         /* Create GC used for inverting */
577         gc_vals.foreground = xc->background;
578         gc_vals.function = GXinvert;
579         xc->invert_gc = XCreateGC(xc->display, xc->xid,
580                                  GCForeground | GCFunction, &gc_vals);
581         XSetSubwindowMode(xc->display, xc->invert_gc,  IncludeInferiors);
582
583         /* Create GC used for drawing */
584         gc_vals.function = GXcopy;
585         gc_vals.foreground = xc->foreground;
586         xc->draw_gc = XCreateGC(xc->display, xc->xid, GCForeground | GCFunction,
587                                 &gc_vals);
588         XSetLineAttributes(xc->display, xc->draw_gc, 0,
589                            LineSolid, CapNotLast, JoinMiter);
590
591         return xc;                                            
592 }
593  
594  
595 /*
596  * Set the clip mask for all gcs the graphics package uses
597  */
598
599 extern void 
600 gr_set_clip_rectangles(new_XContext *xc, int x, int y, XRectangle *rectangles, 
601                        int n, int ordering) {
602
603         XSetClipRectangles(xc->display, xc->gc, x, y, rectangles, n, ordering);
604         XSetClipRectangles(xc->display, xc->draw_gc,
605                            x, y, rectangles, n, ordering);
606         XSetClipRectangles(xc->display, xc->clear_gc,
607                            x, y, rectangles, n, ordering);
608         XSetClipRectangles(xc->display, xc->invert_gc,
609                            x, y, rectangles, n, ordering);
610         return;
611 }
612
613 extern void 
614 gr_clear_clip_rectangles(new_XContext *xc) {
615
616         XSetClipMask(xc->display, xc->gc, None);
617         XSetClipMask(xc->display, xc->draw_gc, None);
618         XSetClipMask(xc->display, xc->clear_gc, None);
619         XSetClipMask(xc->display, xc->invert_gc, None);
620 }
621
622 extern Boolean
623 gr_create_stipple(new_XContext *xc, unsigned char *data, int datawidth, int dataheight, 
624                   Pixmap *stipple, unsigned int *width, unsigned int *height) {
625
626  
627         Boolean ok = True;  
628  
629         if ((*stipple = XCreateBitmapFromData(xc->display,
630                 xc->xid,
631         /*      RootWindow(xc->display, DefaultScreen(xc->display)),  */
632                 (char *)data, datawidth, dataheight)) == 0) {
633                         ok = False;
634                 }
635         else {
636                 *width  = datawidth;
637                 *height = dataheight;
638         }
639         return(ok);
640 }        
641  
642 extern Boolean
643 gr_init(new_XContext *xc, Widget canvas) {
644
645         unsigned int width, height;
646         Boolean ok = True;
647         XColor  rgb_db_ref;
648  
649         Display *dpy = XtDisplay(canvas);
650         int scr = DefaultScreen(dpy);
651         Colormap cmap = DefaultColormap(dpy, scr);
652
653         ok = gr_create_stipple(xc, black_data,     
654                 black_data_width, black_data_height,
655                 &black_data_pixmap, &width, &height);
656         ok = gr_create_stipple(xc, gray_data_75,
657                 gray_data_75_width, gray_data_75_height,
658                 &gray_data_75_pixmap, &width, &height);
659         ok = gr_create_stipple(xc, gray_data_50,
660                 gray_data_50_width, gray_data_50_height,
661                 &gray_data_50_pixmap, &width, &height);
662         ok = gr_create_stipple(xc, gray_data_25,
663                 gray_data_25_width, gray_data_25_height,
664                 &gray_data_25_pixmap, &width, &height);
665
666         ok = XAllocNamedColor(dpy, cmap,                
667                 "dark slate grey", &xc->colorcell_del[DARKGREY], &rgb_db_ref);
668         ok = XAllocNamedColor(dpy, cmap,
669                 "dim grey", &xc->colorcell_del[DIMGREY], &rgb_db_ref);
670         ok = XAllocNamedColor(dpy, cmap,
671                 "grey", &xc->colorcell_del[GREY], &rgb_db_ref);
672         ok = XAllocNamedColor(dpy, cmap,
673                 "light grey", &xc->colorcell_del[LIGHTGREY], &rgb_db_ref);
674         ok = XAllocNamedColor(dpy, cmap,
675                 "red", &xc->colorcell_del[RED], &rgb_db_ref);
676
677         return(ok);                                           
678 }