1 /*******************************************************************************
5 ** $XConsortium: graphics.c /main/3 1995/11/03 10:27:52 rswiston $
7 ** RESTRICTED CONFIDENTIAL INFORMATION:
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
17 ** Copyright 1993 Sun Microsystems, Inc. All rights reserved.
19 *******************************************************************************/
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. *
29 static char sccsid[] = "@(#)graphics.c 1.23 94/11/29 Copyr 1994 Sun Microsystems, Inc.";
32 #include <EUSCompat.h>
35 #include <sys/sysmacros.h>
36 #include <sys/param.h> /* MAXPATHLEN defined here */
38 #include <sys/utsname.h> /* SYS_NMLN */
47 #include <sys/resource.h>
49 #include <netinet/in.h>
51 #include <Xm/DrawingA.h>
53 #include <Xm/RowColumn.h>
54 #include <Xm/ManagerP.h>
55 #include <Xm/GadgetP.h>
59 #include "datefield.h"
73 #include "dayglance.h"
74 #include "yearglance.h"
75 #include "weekglance.h"
87 #include "monthglance.h"
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
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[] = {
116 static unsigned char gray_data_75[] = {
127 static unsigned char gray_data_50[] = {
138 static unsigned char gray_data_25[] = {
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;
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};
162 static unsigned char *dash_list[] = {
173 gr_clear_area(new_XContext *xc, int x, int y, Dimension w, Dimension h) {
175 XFillRectangle(xc->display, xc->xid, xc->clear_gc, x, y, w, h);
177 XClearArea(xc->display, xc->xid, x, y, w, h, False);
182 gr_clear_box (new_XContext *xc, int x, int y, int w, int h) {
184 x+=1; y+=1; w-=1; h-=1;
186 XFillRectangle(xc->display, xc->xid, xc->clear_gc, x, y, w, h);
188 XClearArea(xc->display, xc->xid, x, y, w, h, False);
193 gr_make_grayshade(new_XContext *xc, int x, int y, int w, int h, int shade) {
195 XColor colorcell_del, rgb_db_ref;
197 XSetForeground((Display*)xc->display, (GC)xc->gc, (unsigned long)xc->colorcell_del[shade].pixel);
199 XSetFillStyle(xc->display, xc->gc, FillSolid);
200 XFillRectangle(xc->display, xc->xid, xc->gc, x, y, w, h);
204 gr_make_gray(new_XContext *xc, int x, int y, int w, int h, int percent) {
206 /* Set up gray stipple */
209 XSetStipple(xc->display, xc->gc, gray_data_25_pixmap);
212 XSetStipple(xc->display, xc->gc, gray_data_50_pixmap);
215 XSetStipple(xc->display, xc->gc, gray_data_75_pixmap);
218 XSetStipple(xc->display, xc->gc, gray_data_25_pixmap);
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);
228 gr_make_rgbcolor(new_XContext *xc, Colormap cms, int x, int y, int w, int h,
229 int r, int g, int b) {
231 XColor colorcell_del;
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);
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);
245 gr_nchars(int area, char *str, Cal_Font *font) {
250 int len = cm_strlen(str);
253 CalTextExtents(font, str, len, &nop, &nop, &width, &nop);
257 for (i=0; i<len; i++) {
259 buf = (char *)cm_mbchar(str);
262 buf = (char *)cm_mbchar((char *)NULL);
265 CalTextExtents(font, buf, l, &nop, &nop, &width, &nop);
268 n += mblen(buf, MB_LEN_MAX);
286 XColor colorcell_del, rgb_db_ref;
293 XGetGCValues(xc->display, xc->gc,
294 GCForeground|GCFillStyle, xc->gcvals);
296 pixel = xc->colorcell_del[RED].pixel;
303 XSetForeground((Display*)xc->display, (GC)xc->gc, pixel);
304 XSetFillStyle(xc->display, xc->gc, FillSolid);
306 for (;thickness > 0; thickness--) {
307 XDrawRectangle(xc->display, xc->xid, xc->gc, x, y, w, h);
324 for (;thickness > 0; thickness--) {
325 XDrawRectangle(xc->display, xc->xid, xc->clear_gc, x, y, w, h);
331 /* given an area of a certain length (in pixels), compute
332 where to lay down a string such that it's centered */
335 gr_center(int area, char *str, Cal_Font *font) {
337 int i, strl, l, w, first = 1;
342 strl = cm_strlen(str);
343 for (i=0; i<strl; i++) {
345 buf = (char*)cm_mbchar(str);
348 buf = (char*)cm_mbchar((char *)NULL);
351 CalTextExtents(font, buf, l, &nop, &nop, &width, &nop);
354 return ((area - w)/2);
358 gr_text(new_XContext *xc, int x, int y, Cal_Font *font, char *str,
361 int len = cm_strlen(str);
363 XRectangle overall_ink_return;
366 CalTextExtents(font, str, len, &x2, &y2, &w, &h);
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;
373 if (!myrect_intersectsrect(rect, &overall_ink_return))
376 CalDrawString(xc->display, xc->xid, font, xc->draw_gc, x, y,
377 str, cm_strlen(str));
381 gr_text_rgb(new_XContext *xc, int x, int y, Cal_Font *font, char *str,
382 Pixel shade, Colormap cms, XRectangle *rect) {
384 XRectangle overall_ink_return;
388 CalTextExtents(font, str, cm_strlen(str), &x2, &y2, &w, &h);
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;
395 if (!myrect_intersectsrect(rect, &overall_ink_return))
399 XSetForeground((Display*)xc->display, (GC)xc->gc,
400 (unsigned long)shade);
402 CalDrawString(xc->display, xc->xid, font, xc->gc, x, y,
403 str, cm_strlen(str));
407 gr_draw_line(new_XContext *xc, int x1, int y1, int x2, int y2,
408 GR_Line_Style style, XRectangle *rect) {
417 gr_rect.width = x2-x1;
418 gr_rect.height = y2-y1;
420 if (!myrect_intersectsrect(rect, &gr_rect))
423 if (style==gr_solid) {
424 XDrawLine(xc->display, xc->xid, xc->draw_gc, x1, y1, x2,
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);
441 gr_draw_box(new_XContext *xc, int x, int y, int w, int h, XRectangle *rect) {
451 if (!myrect_intersectsrect(rect, &gr_rect))
454 XDrawRectangle(xc->display, xc->xid, xc->draw_gc, x, y, w, h);
458 gr_draw_glyph(new_XContext *src_xc, new_XContext *dst_xc, Pixmap pixmap,
459 int x, int y, int w, int h) {
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);
467 saturate(XColor *xclr)
472 n = MAX(xclr->red, xclr->green);
473 n = MAX(n, xclr->blue);
485 * Allocate and initialize an XContext
488 gr_create_xcontext(Calendar *c, Widget widget, GR_depth depth, XtAppContext app)
493 XGCValues gc_vals, tmp_vals;
498 /* X Drawing Stuff */
499 if ((xc = (new_XContext *) ckalloc(sizeof(new_XContext))) == NULL)
502 xc->display = (Display *) XtDisplay(widget);
505 if (depth == gr_mono) {
508 xc->hilight_color = 1;
510 XtVaGetValues(widget,
511 XmNbackground, &xc->background,
512 XmNforeground, &xc->foreground,
515 * XXX EEEEEEK! We use a private interface to get the
516 * hilight color. We do this because there is no public
519 hilight_gc = XmParentHighlightGC(widget);
520 XGetGCValues(xc->display, hilight_gc, GCForeground, &tmp_vals);
521 xc->hilight_color = tmp_vals.foreground;
524 xc->xid = XtWindowOfObject(widget);
525 xc->screen_depth = DefaultDepthOfScreen(XtScreen(widget));
528 * Create general purpose gc. This gc is changed as needed by
529 * the drawing routines.
531 xc->gcvals = (XGCValues *) ckalloc(sizeof(XGCValues));
532 xc->gcvals->foreground = xc->foreground;
533 xc->gcvals->background = xc->background;
535 xc->gcvals->fill_style = FillOpaqueStippled;
539 GCForeground|GCBackground|GCFillStyle,
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.
548 /* GC used for clearing */
549 gc_vals.foreground = xc->background;
550 xc->clear_gc = XCreateGC(xc->display, xc->xid, GCForeground, &gc_vals);
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);
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,
564 XSetLineAttributes(xc->display, xc->draw_gc, 0,
565 LineSolid, CapNotLast, JoinMiter);
572 * Set the clip mask for all gcs the graphics package uses
576 gr_set_clip_rectangles(new_XContext *xc, int x, int y, XRectangle *rectangles,
577 int n, int ordering) {
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);
590 gr_clear_clip_rectangles(new_XContext *xc) {
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);
599 gr_create_stipple(new_XContext *xc, unsigned char *data, int datawidth, int dataheight,
600 Pixmap *stipple, unsigned int *width, unsigned int *height) {
605 if ((*stipple = XCreateBitmapFromData(xc->display,
607 /* RootWindow(xc->display, DefaultScreen(xc->display)), */
608 (char *)data, datawidth, dataheight)) == NULL) {
613 *height = dataheight;
619 gr_init(new_XContext *xc, Widget canvas) {
621 unsigned int width, height;
625 Display *dpy = XtDisplay(canvas);
626 int scr = DefaultScreen(dpy);
627 Colormap cmap = DefaultColormap(dpy, scr);
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);
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);