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