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-2007 Daniel A. Steffen <das@users.sourceforge.net>
9 *
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 *
13 * RCS: @(#) $Id: xgc.c,v 1.6.2.6 2007/11/09 06:26:57 das Exp $
14 */
15
16#include <tkInt.h>
17
18#if !defined(MAC_TCL) && !defined(MAC_OSX_TK)
19#	include <X11/Xlib.h>
20#endif
21#ifdef MAC_TCL
22#	include <Xlib.h>
23#	include <X.h>
24#	define Cursor XCursor
25#	define Region XRegion
26#endif
27#ifdef MAC_OSX_TK
28#	include <tkMacOSXInt.h>
29#	include <X11/Xlib.h>
30#	include <X11/X.h>
31#	define Cursor XCursor
32#	define Region XRegion
33#endif
34
35
36/*
37 *----------------------------------------------------------------------
38 *
39 * AllocClipMask --
40 *
41 *	Static helper proc to allocate new or clear existing TkpClipMask.
42 *
43 * Results:
44 *	Returns ptr to the new/cleared TkpClipMask.
45 *
46 * Side effects:
47 *	None.
48 *
49 *----------------------------------------------------------------------
50 */
51
52static TkpClipMask *AllocClipMask(GC gc) {
53    TkpClipMask *clip_mask = (TkpClipMask*) gc->clip_mask;
54
55    if (clip_mask == None) {
56	clip_mask = (TkpClipMask*) ckalloc(sizeof(TkpClipMask));
57	gc->clip_mask = (Pixmap) clip_mask;
58#ifdef MAC_OSX_TK
59    } else if (clip_mask->type == TKP_CLIP_REGION) {
60	TkpReleaseRegion(clip_mask->value.region);
61#endif
62    }
63    return clip_mask;
64}
65
66/*
67 *----------------------------------------------------------------------
68 *
69 * FreeClipMask --
70 *
71 *	Static helper proc to free TkpClipMask.
72 *
73 * Results:
74 *	None.
75 *
76 * Side effects:
77 *	None.
78 *
79 *----------------------------------------------------------------------
80 */
81
82static void FreeClipMask(GC gc) {
83    if (gc->clip_mask != None) {
84#ifdef MAC_OSX_TK
85	if (((TkpClipMask*) gc->clip_mask)->type == TKP_CLIP_REGION) {
86	    TkpReleaseRegion(((TkpClipMask*) gc->clip_mask)->value.region);
87	}
88#endif
89	ckfree((char*) gc->clip_mask);
90	gc->clip_mask = None;
91    }
92}
93
94/*
95 *----------------------------------------------------------------------
96 *
97 * XCreateGC --
98 *
99 *	Allocate a new GC, and initialize the specified fields.
100 *
101 * Results:
102 *	Returns a newly allocated GC.
103 *
104 * Side effects:
105 *	None.
106 *
107 *----------------------------------------------------------------------
108 */
109
110GC
111XCreateGC(display, d, mask, values)
112    Display* display;
113    Drawable d;
114    unsigned long mask;
115    XGCValues* values;
116{
117    GC gp;
118
119/*
120 * In order to have room for a dash list, MAX_DASH_LIST_SIZE extra chars are
121 * defined, which is invisible from the outside. The list is assumed to end
122 * with a 0-char, so this must be set explicitely during initialization.
123 */
124
125#define MAX_DASH_LIST_SIZE 10
126
127    gp = (XGCValues *)ckalloc(sizeof(XGCValues) + MAX_DASH_LIST_SIZE);
128    if (!gp) {
129	return None;
130    }
131
132    gp->function = 	(mask & GCFunction) 	?values->function	:GXcopy;
133    gp->plane_mask = 	(mask & GCPlaneMask) 	?values->plane_mask 	:~0;
134    gp->foreground = 	(mask & GCForeground) 	?values->foreground 	:
135	    BlackPixelOfScreen(DefaultScreenOfDisplay(display));
136    gp->background = 	(mask & GCBackground) 	?values->background 	:
137	    WhitePixelOfScreen(DefaultScreenOfDisplay(display));
138    gp->line_width = 	(mask & GCLineWidth)	?values->line_width	:1;
139    gp->line_style = 	(mask & GCLineStyle)	?values->line_style	:LineSolid;
140    gp->cap_style =  	(mask & GCCapStyle)	?values->cap_style	:0;
141    gp->join_style = 	(mask & GCJoinStyle)	?values->join_style	:0;
142    gp->fill_style =  	(mask & GCFillStyle)	?values->fill_style	:FillSolid;
143    gp->fill_rule =  	(mask & GCFillRule)	?values->fill_rule	:WindingRule;
144    gp->arc_mode = 	(mask & GCArcMode)	?values->arc_mode	:ArcPieSlice;
145    gp->tile = 		(mask & GCTile)		?values->tile		:None;
146    gp->stipple = 	(mask & GCStipple)	?values->stipple	:None;
147    gp->ts_x_origin = 	(mask & GCTileStipXOrigin)	?values->ts_x_origin:0;
148    gp->ts_y_origin = 	(mask & GCTileStipYOrigin)	?values->ts_y_origin:0;
149    gp->font = 		(mask & GCFont)		?values->font		:None;
150    gp->subwindow_mode = (mask & GCSubwindowMode)?values->subwindow_mode:ClipByChildren;
151    gp->graphics_exposures = (mask & GCGraphicsExposures)?values->graphics_exposures:True;
152    gp->clip_x_origin = (mask & GCClipXOrigin)	?values->clip_x_origin	:0;
153    gp->clip_y_origin = (mask & GCClipYOrigin)	?values->clip_y_origin	:0;
154    gp->dash_offset = 	(mask & GCDashOffset)	?values->dash_offset	:0;
155    gp->dashes = 	(mask & GCDashList)	?values->dashes		:4;
156    (&(gp->dashes))[1] = 	0;
157
158    gp->clip_mask = None;
159    if (mask & GCClipMask) {
160	TkpClipMask *clip_mask = AllocClipMask(gp);
161
162	clip_mask->type = TKP_CLIP_PIXMAP;
163	clip_mask->value.pixmap = values->clip_mask;
164    }
165
166    return gp;
167}
168
169/*
170 *----------------------------------------------------------------------
171 *
172 * XChangeGC --
173 *
174 *	Changes the GC components specified by valuemask for the
175 *	specified GC.
176 *
177 * Results:
178 *	None.
179 *
180 * Side effects:
181 *	Updates the specified GC.
182 *
183 *----------------------------------------------------------------------
184 */
185
186void
187XChangeGC(d, gc, mask, values)
188    Display * d;
189    GC gc;
190    unsigned long mask;
191    XGCValues *values;
192{
193    if (mask & GCFunction) { gc->function = values->function; }
194    if (mask & GCPlaneMask) { gc->plane_mask = values->plane_mask; }
195    if (mask & GCForeground) { gc->foreground = values->foreground; }
196    if (mask & GCBackground) { gc->background = values->background; }
197    if (mask & GCLineWidth) { gc->line_width = values->line_width; }
198    if (mask & GCLineStyle) { gc->line_style = values->line_style; }
199    if (mask & GCCapStyle) { gc->cap_style = values->cap_style; }
200    if (mask & GCJoinStyle) { gc->join_style = values->join_style; }
201    if (mask & GCFillStyle) { gc->fill_style = values->fill_style; }
202    if (mask & GCFillRule) { gc->fill_rule = values->fill_rule; }
203    if (mask & GCArcMode) { gc->arc_mode = values->arc_mode; }
204    if (mask & GCTile) { gc->tile = values->tile; }
205    if (mask & GCStipple) { gc->stipple = values->stipple; }
206    if (mask & GCTileStipXOrigin) { gc->ts_x_origin = values->ts_x_origin; }
207    if (mask & GCTileStipYOrigin) { gc->ts_y_origin = values->ts_y_origin; }
208    if (mask & GCFont) { gc->font = values->font; }
209    if (mask & GCSubwindowMode) { gc->subwindow_mode = values->subwindow_mode; }
210    if (mask & GCGraphicsExposures) { gc->graphics_exposures = values->graphics_exposures; }
211    if (mask & GCClipXOrigin) { gc->clip_x_origin = values->clip_x_origin; }
212    if (mask & GCClipYOrigin) { gc->clip_y_origin = values->clip_y_origin; }
213    if (mask & GCClipMask) { XSetClipMask(d, gc, values->clip_mask); }
214    if (mask & GCDashOffset) { gc->dash_offset = values->dash_offset; }
215    if (mask & GCDashList) { gc->dashes = values->dashes; (&(gc->dashes))[1] = 0;}
216}
217
218/*
219 *----------------------------------------------------------------------
220 *
221 * XFreeGC --
222 *
223 *	Deallocates the specified graphics context.
224 *
225 * Results:
226 *	None.
227 *
228 * Side effects:
229 *	None.
230 *
231 *----------------------------------------------------------------------
232 */
233
234void XFreeGC(d, gc)
235    Display * d;
236    GC gc;
237{
238    if (gc != None) {
239	FreeClipMask(gc);
240	ckfree((char *) gc);
241    }
242}
243
244/*
245 *----------------------------------------------------------------------
246 *
247 * XSetForeground, etc. --
248 *
249 *	The following functions are simply accessor functions for
250 *	the GC slots.
251 *
252 * Results:
253 *	None.
254 *
255 * Side effects:
256 *	Each function sets some slot in the GC.
257 *
258 *----------------------------------------------------------------------
259 */
260
261void
262XSetForeground(display, gc, foreground)
263    Display *display;
264    GC gc;
265    unsigned long foreground;
266{
267    gc->foreground = foreground;
268}
269
270void
271XSetBackground(display, gc, background)
272    Display *display;
273    GC gc;
274    unsigned long background;
275{
276    gc->background = background;
277}
278
279void
280XSetDashes(display, gc, dash_offset, dash_list, n)
281    Display* display;
282    GC gc;
283    int dash_offset;
284    _Xconst char* dash_list;
285    int n;
286{
287    char *p = &(gc->dashes);
288
289#ifdef TkWinDeleteBrush
290    TkWinDeleteBrush(gc->fgBrush);
291    TkWinDeletePen(gc->fgPen);
292    TkWinDeleteBrush(gc->bgBrush);
293    TkWinDeletePen(gc->fgExtPen);
294#endif
295    gc->dash_offset = dash_offset;
296    if (n > MAX_DASH_LIST_SIZE) n = MAX_DASH_LIST_SIZE;
297    while (n-- > 0) {
298	*p++ = *dash_list++;
299    }
300    *p = 0;
301}
302
303void
304XSetFunction(display, gc, function)
305    Display *display;
306    GC gc;
307    int function;
308{
309    gc->function = function;
310}
311
312void
313XSetFillRule(display, gc, fill_rule)
314    Display *display;
315    GC gc;
316    int fill_rule;
317{
318    gc->fill_rule = fill_rule;
319}
320
321void
322XSetFillStyle(display, gc, fill_style)
323    Display *display;
324    GC gc;
325    int fill_style;
326{
327    gc->fill_style = fill_style;
328}
329
330void
331XSetTSOrigin(display, gc, x, y)
332    Display *display;
333    GC gc;
334    int x, y;
335{
336    gc->ts_x_origin = x;
337    gc->ts_y_origin = y;
338}
339
340void
341XSetFont(display, gc, font)
342    Display *display;
343    GC gc;
344    Font font;
345{
346    gc->font = font;
347}
348
349void
350XSetArcMode(display, gc, arc_mode)
351    Display *display;
352    GC gc;
353    int arc_mode;
354{
355    gc->arc_mode = arc_mode;
356}
357
358void
359XSetStipple(display, gc, stipple)
360    Display *display;
361    GC gc;
362    Pixmap stipple;
363{
364    gc->stipple = stipple;
365}
366
367void
368XSetLineAttributes(display, gc, line_width, line_style, cap_style,
369	join_style)
370    Display *display;
371    GC gc;
372    unsigned int line_width;
373    int line_style;
374    int cap_style;
375    int join_style;
376{
377    gc->line_width = line_width;
378    gc->line_style = line_style;
379    gc->cap_style = cap_style;
380    gc->join_style = join_style;
381}
382
383void
384XSetClipOrigin(display, gc, clip_x_origin, clip_y_origin)
385    Display* display;
386    GC gc;
387    int clip_x_origin;
388    int clip_y_origin;
389{
390    gc->clip_x_origin = clip_x_origin;
391    gc->clip_y_origin = clip_y_origin;
392}
393
394/*
395 *----------------------------------------------------------------------
396 *
397 * TkSetRegion, XSetClipMask --
398 *
399 *	Sets the clipping region/pixmap for a GC.
400 *
401 *	Note that unlike the Xlib equivalent, it is not safe to delete the
402 *	region after setting it into the GC (except on Mac OS X). The only
403 *	uses of TkSetRegion are currently in DisplayFrame and in
404 *	ImgPhotoDisplay, which use the GC immediately.
405 *
406 * Results:
407 *	None.
408 *
409 * Side effects:
410 *	Allocates or dealloates a TkpClipMask.
411 *
412 *----------------------------------------------------------------------
413 */
414
415void
416TkSetRegion(display, gc, r)
417    Display* display;
418    GC gc;
419    TkRegion r;
420{
421    if (r == None) {
422	FreeClipMask(gc);
423    } else {
424	TkpClipMask *clip_mask = AllocClipMask(gc);
425
426	clip_mask->type = TKP_CLIP_REGION;
427	clip_mask->value.region = r;
428#ifdef MAC_OSX_TK
429	TkpRetainRegion(r);
430#endif
431    }
432}
433
434void
435XSetClipMask(display, gc, pixmap)
436    Display* display;
437    GC gc;
438    Pixmap pixmap;
439{
440    if (pixmap == None) {
441	FreeClipMask(gc);
442    } else {
443	TkpClipMask *clip_mask = AllocClipMask(gc);
444
445	clip_mask->type = TKP_CLIP_PIXMAP;
446	clip_mask->value.pixmap = pixmap;
447    }
448}
449
450/*
451 * Some additional dummy functions (hopefully implemented soon).
452 */
453
454#if 0
455Cursor
456XCreateFontCursor(display, shape)
457    Display* display;
458    unsigned int shape;
459{
460    return (Cursor) 0;
461}
462
463void
464XDrawImageString(display, d, gc, x, y, string, length)
465    Display* display;
466    Drawable d;
467    GC gc;
468    int x;
469    int y;
470    _Xconst char* string;
471    int length;
472{
473}
474#endif
475
476void
477XDrawPoint(display, d, gc, x, y)
478    Display* display;
479    Drawable d;
480    GC gc;
481    int x;
482    int y;
483{
484    XDrawLine(display, d, gc, x, y, x, y);
485}
486
487void
488XDrawPoints(display, d, gc, points, npoints, mode)
489    Display* display;
490    Drawable d;
491    GC gc;
492    XPoint* points;
493    int npoints;
494    int mode;
495{
496    int i;
497
498    for (i=0; i<npoints; i++) {
499	XDrawPoint(display, d, gc, points[i].x, points[i].y);
500    }
501}
502
503#if !defined(MAC_TCL) && !defined(MAC_OSX_TK)
504void
505XDrawSegments(display, d, gc, segments, nsegments)
506    Display* display;
507    Drawable d;
508    GC gc;
509    XSegment* segments;
510    int nsegments;
511{
512}
513#endif
514
515#if 0
516char *
517XFetchBuffer(display, nbytes_return, buffer)
518    Display* display;
519    int* nbytes_return;
520    int buffer;
521{
522    return (char *) 0;
523}
524
525Status XFetchName(display, w, window_name_return)
526    Display* display;
527    Window w;
528    char** window_name_return;
529{
530    return (Status) 0;
531}
532
533Atom *XListProperties(display, w, num_prop_return)
534    Display* display;
535    Window w;
536    int* num_prop_return;
537{
538    return (Atom *) 0;
539}
540
541void
542XMapRaised(display, w)
543    Display* display;
544    Window w;
545{
546}
547
548void
549XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height)
550    Display* display;
551    Drawable d;
552    GC gc;
553    XImage* image;
554    int src_x;
555    int src_y;
556    int dest_x;
557    int dest_y;
558    unsigned int width;
559    unsigned int height;
560{
561}
562
563void
564XQueryTextExtents(display, font_ID, string, nchars, direction_return,
565	font_ascent_return, font_descent_return, overall_return)
566    Display* display;
567    XID font_ID;
568    _Xconst char* string;
569    int nchars;
570    int* direction_return;
571    int* font_ascent_return;
572    int* font_descent_return;
573    XCharStruct* overall_return;
574{
575}
576
577void
578XReparentWindow(display, w, parent, x, y)
579    Display* display;
580    Window w;
581    Window parent;
582    int x;
583    int y;
584{
585}
586
587void
588XRotateBuffers(display, rotate)
589    Display* display;
590    int rotate;
591{
592}
593
594void
595XStoreBuffer(display, bytes, nbytes, buffer)
596    Display* display;
597    _Xconst char* bytes;
598    int nbytes;
599    int buffer;
600{
601}
602
603void
604XUndefineCursor(display, w)
605    Display* display;
606    Window w;
607{
608}
609#endif
610