1 /*
2  * xgc.c --
3  *
4  *	This file contains generic routines for manipulating X graphics
5  *	contexts.
6  *
7  * Copyright (c) 1995-1996 Sun Microsystems, Inc.
8  * Copyright (c) 2002-2009 Daniel A. Steffen <das@users.sourceforge.net>
9  * Copyright 2008-2009, Apple Inc.
10  *
11  * See the file "license.terms" for information on usage and redistribution of
12  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
13  */
14 
15 #include "tkInt.h"
16 #include <X11/Xlib.h>
17 #if defined(MAC_OSX_TK)
18 #   define Cursor XCursor
19 #   define Region XRegion
20 #endif
21 
22 #undef TkSetRegion
23 
24 #define MAX_DASH_LIST_SIZE 10
25 typedef struct {
26     XGCValues gc;
27     char dash[MAX_DASH_LIST_SIZE];
28 } XGCValuesWithDash;
29 
30 /*
31  *----------------------------------------------------------------------
32  *
33  * AllocClipMask --
34  *
35  *	Static helper proc to allocate new or clear existing TkpClipMask.
36  *
37  * Results:
38  *	Returns ptr to the new/cleared TkpClipMask.
39  *
40  * Side effects:
41  *	None.
42  *
43  *----------------------------------------------------------------------
44  */
45 
AllocClipMask(GC gc)46 static TkpClipMask *AllocClipMask(GC gc) {
47     TkpClipMask *clip_mask = (TkpClipMask*) gc->clip_mask;
48 
49     if (clip_mask == NULL) {
50 	clip_mask = (TkpClipMask *)ckalloc(sizeof(TkpClipMask));
51 	gc->clip_mask = (Pixmap) clip_mask;
52     }
53     return clip_mask;
54 }
55 
56 /*
57  *----------------------------------------------------------------------
58  *
59  * FreeClipMask --
60  *
61  *	Static helper proc to free TkpClipMask.
62  *
63  * Results:
64  *	None.
65  *
66  * Side effects:
67  *	None.
68  *
69  *----------------------------------------------------------------------
70  */
71 
FreeClipMask(GC gc)72 static void FreeClipMask(GC gc) {
73     if (gc->clip_mask != None) {
74 	ckfree((char *)gc->clip_mask);
75 	gc->clip_mask = None;
76     }
77 }
78 
79 /*
80  *----------------------------------------------------------------------
81  *
82  * XCreateGC --
83  *
84  *	Allocate a new GC, and initialize the specified fields.
85  *
86  * Results:
87  *	Returns a newly allocated GC.
88  *
89  * Side effects:
90  *	None.
91  *
92  *----------------------------------------------------------------------
93  */
94 
95 GC
XCreateGC(Display * display,Drawable d,unsigned long mask,XGCValues * values)96 XCreateGC(
97     Display *display,
98     Drawable d,
99     unsigned long mask,
100     XGCValues *values)
101 {
102     GC gp;
103     (void)d;
104 
105     /*
106      * In order to have room for a dash list, MAX_DASH_LIST_SIZE extra chars
107      * are defined, which is invisible from the outside. The list is assumed
108      * to end with a 0-char, so this must be set explicitly during
109      * initialization.
110      */
111 
112     gp = (GC)ckalloc(sizeof(XGCValuesWithDash));
113     if (!gp) {
114 	return NULL;
115     }
116 
117 #define InitField(name,maskbit,default) \
118 	(gp->name = (mask & (maskbit)) ? values->name : (default))
119 
120     InitField(function,		  GCFunction,		GXcopy);
121     InitField(plane_mask,	  GCPlaneMask,		(unsigned long)(~0));
122     InitField(foreground,	  GCForeground,
123 	    BlackPixelOfScreen(DefaultScreenOfDisplay(display)));
124     InitField(background,	  GCBackground,
125 	    WhitePixelOfScreen(DefaultScreenOfDisplay(display)));
126     InitField(line_width,	  GCLineWidth,		1);
127     InitField(line_style,	  GCLineStyle,		LineSolid);
128     InitField(cap_style,	  GCCapStyle,		0);
129     InitField(join_style,	  GCJoinStyle,		0);
130     InitField(fill_style,	  GCFillStyle,		FillSolid);
131     InitField(fill_rule,	  GCFillRule,		WindingRule);
132     InitField(arc_mode,		  GCArcMode,		ArcPieSlice);
133     InitField(tile,		  GCTile,		0);
134     InitField(stipple,		  GCStipple,		0);
135     InitField(ts_x_origin,	  GCTileStipXOrigin,	0);
136     InitField(ts_y_origin,	  GCTileStipYOrigin,	0);
137     InitField(font,		  GCFont,		0);
138     InitField(subwindow_mode,	  GCSubwindowMode,	ClipByChildren);
139     InitField(graphics_exposures, GCGraphicsExposures,	True);
140     InitField(clip_x_origin,	  GCClipXOrigin,	0);
141     InitField(clip_y_origin,	  GCClipYOrigin,	0);
142     InitField(dash_offset,	  GCDashOffset,		0);
143     InitField(dashes,		  GCDashList,		4);
144     (&(gp->dashes))[1] = 0;
145 
146     gp->clip_mask = None;
147     if (mask & GCClipMask) {
148 	TkpClipMask *clip_mask = AllocClipMask(gp);
149 
150 	clip_mask->type = TKP_CLIP_PIXMAP;
151 	clip_mask->value.pixmap = values->clip_mask;
152     }
153     return gp;
154 }
155 
156 /*
157  *----------------------------------------------------------------------
158  *
159  * XChangeGC --
160  *
161  *	Changes the GC components specified by valuemask for the specified GC.
162  *
163  * Results:
164  *	None.
165  *
166  * Side effects:
167  *	Updates the specified GC.
168  *
169  *----------------------------------------------------------------------
170  */
171 
172 int
XChangeGC(Display * d,GC gc,unsigned long mask,XGCValues * values)173 XChangeGC(
174     Display *d,
175     GC gc,
176     unsigned long mask,
177     XGCValues *values)
178 {
179 #define ModifyField(name,maskbit) \
180 	if (mask & (maskbit)) { gc->name = values->name; }
181 
182     ModifyField(function, GCFunction);
183     ModifyField(plane_mask, GCPlaneMask);
184     ModifyField(foreground, GCForeground);
185     ModifyField(background, GCBackground);
186     ModifyField(line_width, GCLineWidth);
187     ModifyField(line_style, GCLineStyle);
188     ModifyField(cap_style, GCCapStyle);
189     ModifyField(join_style, GCJoinStyle);
190     ModifyField(fill_style, GCFillStyle);
191     ModifyField(fill_rule, GCFillRule);
192     ModifyField(arc_mode, GCArcMode);
193     ModifyField(tile, GCTile);
194     ModifyField(stipple, GCStipple);
195     ModifyField(ts_x_origin, GCTileStipXOrigin);
196     ModifyField(ts_y_origin, GCTileStipYOrigin);
197     ModifyField(font, GCFont);
198     ModifyField(subwindow_mode, GCSubwindowMode);
199     ModifyField(graphics_exposures, GCGraphicsExposures);
200     ModifyField(clip_x_origin, GCClipXOrigin);
201     ModifyField(clip_y_origin, GCClipYOrigin);
202     ModifyField(dash_offset, GCDashOffset);
203     if (mask & GCClipMask) {
204 	XSetClipMask(d, gc, values->clip_mask);
205     }
206     if (mask & GCDashList) {
207 	gc->dashes = values->dashes;
208 	(&(gc->dashes))[1] = 0;
209     }
210     return Success;
211 }
212 
213 /*
214  *----------------------------------------------------------------------
215  *
216  * XFreeGC --
217  *
218  *	Deallocates the specified graphics context.
219  *
220  * Results:
221  *	None.
222  *
223  * Side effects:
224  *	None.
225  *
226  *----------------------------------------------------------------------
227  */
228 
XFreeGC(Display * d,GC gc)229 int XFreeGC(
230     Display *d,
231     GC gc)
232 {
233     (void)d;
234 
235     if (gc != NULL) {
236 	FreeClipMask(gc);
237 	ckfree(gc);
238     }
239     return Success;
240 }
241 
242 /*
243  *----------------------------------------------------------------------
244  *
245  * XSetForeground, etc. --
246  *
247  *	The following functions are simply accessor functions for the GC
248  *	slots.
249  *
250  * Results:
251  *	None.
252  *
253  * Side effects:
254  *	Each function sets some slot in the GC.
255  *
256  *----------------------------------------------------------------------
257  */
258 
259 int
XSetForeground(Display * display,GC gc,unsigned long foreground)260 XSetForeground(
261     Display *display,
262     GC gc,
263     unsigned long foreground)
264 {
265     (void)display;
266 
267     gc->foreground = foreground;
268     return Success;
269 }
270 
271 int
XSetBackground(Display * display,GC gc,unsigned long background)272 XSetBackground(
273     Display *display,
274     GC gc,
275     unsigned long background)
276 {
277     (void)display;
278 
279     gc->background = background;
280     return Success;
281 }
282 
283 int
XSetDashes(Display * display,GC gc,int dash_offset,_Xconst char * dash_list,int n)284 XSetDashes(
285     Display *display,
286     GC gc,
287     int dash_offset,
288     _Xconst char *dash_list,
289     int n)
290 {
291     char *p = &(gc->dashes);
292     (void)display;
293 
294 #ifdef TkWinDeleteBrush
295     TkWinDeleteBrush(gc->fgBrush);
296     TkWinDeletePen(gc->fgPen);
297     TkWinDeleteBrush(gc->bgBrush);
298     TkWinDeletePen(gc->fgExtPen);
299 #endif
300     gc->dash_offset = dash_offset;
301     if (n > MAX_DASH_LIST_SIZE) n = MAX_DASH_LIST_SIZE;
302     while (n-- > 0) {
303 	*p++ = *dash_list++;
304     }
305     *p = 0;
306     return Success;
307 }
308 
309 int
XSetFunction(Display * display,GC gc,int function)310 XSetFunction(
311     Display *display,
312     GC gc,
313     int function)
314 {
315     (void)display;
316 
317     gc->function = function;
318     return Success;
319 }
320 
321 int
XSetFillRule(Display * display,GC gc,int fill_rule)322 XSetFillRule(
323     Display *display,
324     GC gc,
325     int fill_rule)
326 {
327     (void)display;
328 
329     gc->fill_rule = fill_rule;
330     return Success;
331 }
332 
333 int
XSetFillStyle(Display * display,GC gc,int fill_style)334 XSetFillStyle(
335     Display *display,
336     GC gc,
337     int fill_style)
338 {
339     (void)display;
340 
341     gc->fill_style = fill_style;
342     return Success;
343 }
344 
345 int
XSetTSOrigin(Display * display,GC gc,int x,int y)346 XSetTSOrigin(
347     Display *display,
348     GC gc,
349     int x, int y)
350 {
351     (void)display;
352 
353     gc->ts_x_origin = x;
354     gc->ts_y_origin = y;
355     return Success;
356 }
357 
358 int
XSetFont(Display * display,GC gc,Font font)359 XSetFont(
360     Display *display,
361     GC gc,
362     Font font)
363 {
364     (void)display;
365 
366     gc->font = font;
367     return Success;
368 }
369 
370 int
XSetArcMode(Display * display,GC gc,int arc_mode)371 XSetArcMode(
372     Display *display,
373     GC gc,
374     int arc_mode)
375 {
376     (void)display;
377 
378     gc->arc_mode = arc_mode;
379     return Success;
380 }
381 
382 int
XSetStipple(Display * display,GC gc,Pixmap stipple)383 XSetStipple(
384     Display *display,
385     GC gc,
386     Pixmap stipple)
387 {
388     (void)display;
389 
390     gc->stipple = stipple;
391     return Success;
392 }
393 
394 int
XSetLineAttributes(Display * display,GC gc,unsigned int line_width,int line_style,int cap_style,int join_style)395 XSetLineAttributes(
396     Display *display,
397     GC gc,
398     unsigned int line_width,
399     int line_style,
400     int cap_style,
401     int join_style)
402 {
403     (void)display;
404 
405     gc->line_width = line_width;
406     gc->line_style = line_style;
407     gc->cap_style = cap_style;
408     gc->join_style = join_style;
409     return Success;
410 }
411 
412 int
XSetClipOrigin(Display * display,GC gc,int clip_x_origin,int clip_y_origin)413 XSetClipOrigin(
414     Display *display,
415     GC gc,
416     int clip_x_origin,
417     int clip_y_origin)
418 {
419     (void)display;
420 
421     gc->clip_x_origin = clip_x_origin;
422     gc->clip_y_origin = clip_y_origin;
423     return Success;
424 }
425 
426 /*
427  *----------------------------------------------------------------------
428  *
429  * TkSetRegion, XSetClipMask --
430  *
431  *	Sets the clipping region/pixmap for a GC.
432  *
433  *	Note that unlike the Xlib equivalent, it is not safe to delete the
434  *	region after setting it into the GC (except on Mac OS X). The only
435  *	uses of TkSetRegion are currently in DisplayFrame and in
436  *	ImgPhotoDisplay, which use the GC immediately.
437  *
438  * Results:
439  *	None.
440  *
441  * Side effects:
442  *	Allocates or deallocates a TkpClipMask.
443  *
444  *----------------------------------------------------------------------
445  */
446 
447 int
TkSetRegion(Display * display,GC gc,TkRegion r)448 TkSetRegion(
449     Display *display,
450     GC gc,
451     TkRegion r)
452 {
453     (void)display;
454 
455     if (r == NULL) {
456 	Tcl_Panic("must not pass NULL to TkSetRegion for compatibility with X11; use XSetClipMask instead");
457     } else {
458 	TkpClipMask *clip_mask = AllocClipMask(gc);
459 
460 	clip_mask->type = TKP_CLIP_REGION;
461 	clip_mask->value.region = r;
462     }
463     return Success;
464 }
465 
466 int
XSetClipMask(Display * display,GC gc,Pixmap pixmap)467 XSetClipMask(
468     Display *display,
469     GC gc,
470     Pixmap pixmap)
471 {
472     (void)display;
473 
474     if (pixmap == None) {
475 	FreeClipMask(gc);
476     } else {
477 	TkpClipMask *clip_mask = AllocClipMask(gc);
478 
479 	clip_mask->type = TKP_CLIP_PIXMAP;
480 	clip_mask->value.pixmap = pixmap;
481     }
482     return Success;
483 }
484 
485 /*
486  * Some additional dummy functions (hopefully implemented soon).
487  */
488 
489 #if 0
490 Cursor
491 XCreateFontCursor(
492     Display *display,
493     unsigned int shape)
494 {
495     return (Cursor) 0;
496 }
497 
498 void
499 XDrawImageString(
500     Display *display,
501     Drawable d,
502     GC gc,
503     int x,
504     int y,
505     _Xconst char *string,
506     int length)
507 {
508 }
509 #endif
510 
511 int
XDrawPoint(Display * display,Drawable d,GC gc,int x,int y)512 XDrawPoint(
513     Display *display,
514     Drawable d,
515     GC gc,
516     int x,
517     int y)
518 {
519     return XDrawLine(display, d, gc, x, y, x, y);
520 }
521 
522 int
XDrawPoints(Display * display,Drawable d,GC gc,XPoint * points,int npoints,int mode)523 XDrawPoints(
524     Display *display,
525     Drawable d,
526     GC gc,
527     XPoint *points,
528     int npoints,
529     int mode)
530 {
531     int res = Success;
532     (void)mode;
533 
534     while (npoints-- > 0) {
535 	res = XDrawLine(display, d, gc,
536 		points[0].x, points[0].y, points[0].x, points[0].y);
537 	if (res != Success) break;
538 	++points;
539     }
540     return res;
541 }
542 
543 #if !defined(MAC_OSX_TK)
544 int
XDrawSegments(Display * display,Drawable d,GC gc,XSegment * segments,int nsegments)545 XDrawSegments(
546     Display *display,
547     Drawable d,
548     GC gc,
549     XSegment *segments,
550     int nsegments)
551 {
552     (void)display;
553     (void)d;
554     (void)gc;
555     (void)segments;
556     (void)nsegments;
557 
558     return BadDrawable;
559 }
560 #endif
561 
562 #if 0
563 char *
564 XFetchBuffer(
565     Display *display,
566     int *nbytes_return,
567     int buffer)
568 {
569     (void)display;
570     (void)nbytes_return;
571     (void)buffer;
572 
573     return (char *) 0;
574 }
575 
576 Status
577 XFetchName(
578     Display *display,
579     Window w,
580     char **window_name_return)
581 {
582     (void)display;
583     (void)w;
584     (void)window_name_return;
585 
586     return Success;
587 }
588 
589 Atom *
590 XListProperties(
591     Display* display,
592     Window w,
593     int *num_prop_return)
594 {
595     (void)display;
596     (void)w;
597     (void)num_prop_return;
598 
599     return (Atom *) 0;
600 }
601 
602 int
603 XMapRaised(
604     Display *display,
605     Window w)
606 {
607     (void)display;
608     (void)w;
609 
610     return Success;
611 }
612 
613 int
614 XQueryTextExtents(
615     Display *display,
616     XID font_ID,
617     _Xconst char *string,
618     int nchars,
619     int *direction_return,
620     int *font_ascent_return,
621     int *font_descent_return,
622     XCharStruct *overall_return)
623 {
624     (void)display;
625     (void)font_ID;
626     (void)string;
627     (void)nchars;
628     (void)direction_return;
629     (void)font_ascent_return;
630     (void)font_descent_return;
631     (void)overall_return;
632 
633     return Success;
634 }
635 
636 int
637 XReparentWindow(
638     Display *display,
639     Window w,
640     Window parent,
641     int x,
642     int y)
643 {
644     (void)display;
645     (void)w;
646     (void)parent;
647     (void)x;
648     (void)y;
649 
650     return BadWindow;
651 }
652 
653 int
654 XUndefineCursor(
655     Display *display,
656     Window w)
657 {
658     (void)display;
659     (void)w;
660 
661     return Success;
662 }
663 
664 XVaNestedList
665 XVaCreateNestedList(
666     int unused, ...)
667 {
668     (void)unused;
669     return NULL;
670 }
671 
672 char *
673 XSetICValues(
674     XIC xic, ...)
675 {
676     (void)xic;
677     return NULL;
678 }
679 
680 char *
681 XGetICValues(
682     XIC xic, ...)
683 {
684     (void)xic;
685     return NULL;
686 }
687 
688 void
689 XSetICFocus(
690     XIC xic)
691 {
692     (void)xic;
693 }
694 
695 Window
696 XCreateWindow(
697     Display *display,
698 	Window parent,
699 	int x,
700 	int y,
701     unsigned int width,
702 	unsigned int height,
703     unsigned int border_width,
704 	int depth,
705 	unsigned int clazz,
706     Visual *visual,
707 	unsigned long value_mask,
708     XSetWindowAttributes *attributes)
709 {
710     (void)display;
711     (void)parent;
712     (void)x;
713     (void)y;
714     (void)width;
715     (void)height;
716     (void)border_width;
717     (void)depth;
718     (void)clazz;
719     (void)visual;
720     (void)value_mask;
721     (void)attributes;
722 
723 	return 0;
724 }
725 
726 int
727 XPointInRegion(
728     Region rgn,
729 	int x,
730 	int y)
731 {
732     (void)rgn;
733     (void)x;
734     (void)y;
735 
736 	return 0;
737 }
738 
739 int
740 XUnionRegion(
741     Region srca,
742 	Region srcb,
743 	Region dr_return)
744 {
745     (void)srca;
746     (void)srcb;
747     (void)dr_return;
748 
749 	return 0;
750 }
751 
752 Region
753 XPolygonRegion(
754     XPoint *pts,
755 	int n,
756 	int rule)
757 {
758     (void)pts;
759     (void)n;
760     (void)rule;
761 
762     return 0;
763 }
764 #endif
765 
766 void
XDestroyIC(XIC ic)767 XDestroyIC(
768     XIC ic)
769 {
770     (void)ic;
771 }
772 
773 Cursor
XCreatePixmapCursor(Display * display,Pixmap source,Pixmap mask,XColor * foreground_color,XColor * background_color,unsigned int x,unsigned int y)774 XCreatePixmapCursor(
775     Display *display,
776     Pixmap source,
777     Pixmap mask,
778     XColor *foreground_color,
779     XColor *background_color,
780     unsigned int x,
781     unsigned int y)
782 {
783     (void)display;
784     (void)source;
785     (void)mask;
786     (void)foreground_color;
787     (void)background_color;
788     (void)x;
789     (void)y;
790 
791     return (Cursor) NULL;
792 }
793 
794 Cursor
XCreateGlyphCursor(Display * display,Font source_font,Font mask_font,unsigned int source_char,unsigned int mask_char,XColor _Xconst * foreground_color,XColor _Xconst * background_color)795 XCreateGlyphCursor(
796     Display *display,
797     Font source_font,
798     Font mask_font,
799     unsigned int source_char,
800     unsigned int mask_char,
801     XColor _Xconst *foreground_color,
802     XColor _Xconst *background_color)
803 {
804     (void)display;
805     (void)source_font;
806     (void)mask_font;
807     (void)source_char;
808     (void)mask_char;
809     (void)foreground_color;
810     (void)background_color;
811 
812     return (Cursor) NULL;
813 }
814 
815 #if 0
816 XFontSet
817 XCreateFontSet(
818     Display *display		/* display */,
819     _Xconst char *base_font_name_list	/* base_font_name_list */,
820     char ***missing_charset_list		/* missing_charset_list */,
821     int *missing_charset_count		/* missing_charset_count */,
822     char **def_string		/* def_string */
823 ) {
824     (void)display;
825     (void)base_font_name_list;
826     (void)missing_charset_list;
827     (void)missing_charset_count;
828     (void)def_string;
829 
830     return (XFontSet)0;
831 }
832 
833 void
834 XFreeFontSet(
835     Display *display,		/* display */
836     XFontSet fontset		/* font_set */
837 ) {
838     (void)display;
839     (void)fontset;
840 }
841 
842 void
843 XFreeStringList(
844     char **list		/* list */
845 ) {
846     (void)list;
847 }
848 
849 Status
850 XCloseIM(
851     XIM im /* im */
852 ) {
853     (void)im;
854 
855     return Success;
856 }
857 
858 Bool
859 XRegisterIMInstantiateCallback(
860     Display *dpy			/* dpy */,
861     struct _XrmHashBucketRec *rdb	/* rdb */,
862     char *res_name			/* res_name */,
863     char *res_class			/* res_class */,
864     XIDProc callback			/* callback */,
865     XPointer client_data			/* client_data */
866 ) {
867     (void)dpy;
868     (void)rdb;
869     (void)res_name;
870     (void)res_class;
871     (void)callback;
872     (void)client_data;
873 
874     return False;
875 }
876 
877 Bool
878 XUnregisterIMInstantiateCallback(
879     Display *dpy			/* dpy */,
880     struct _XrmHashBucketRec *rdb	/* rdb */,
881     char *res_name			/* res_name */,
882     char *res_class			/* res_class */,
883     XIDProc callback			/* callback */,
884     XPointer client_data			/* client_data */
885 ) {
886     (void)dpy;
887     (void)rdb;
888     (void)res_name;
889     (void)res_class;
890     (void)callback;
891     (void)client_data;
892 
893     return False;
894 }
895 
896 char *
897 XSetLocaleModifiers(
898     const char *modifier_list		/* modifier_list */
899 ) {
900     (void)modifier_list;
901 
902     return NULL;
903 }
904 
905 XIM XOpenIM(
906     Display *dpy			/* dpy */,
907     struct _XrmHashBucketRec *rdb	/* rdb */,
908     char *res_name			/* res_name */,
909     char *res_class			/* res_class */
910 ) {
911     (void)dpy;
912     (void)rdb;
913     (void)res_name;
914     (void)res_class;
915 
916     return NULL;
917 }
918 
919 char *
920 XGetIMValues(
921     XIM im /* im */, ...
922 ) {
923     (void)im;
924 
925     return NULL;
926 }
927 
928 char *
929 XSetIMValues(
930     XIM im /* im */, ...
931 ) {
932     (void)im;
933 
934     return NULL;
935 }
936 #endif
937 
938 /*
939  * Local Variables:
940  * mode: c
941  * c-basic-offset: 4
942  * fill-column: 78
943  * End:
944  */
945