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