]> Pileus Git - ~andy/gtk/blob - gdk/gdkgc.c
[ Merges from gtk-1-2 ]
[~andy/gtk] / gdk / gdkgc.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <string.h>
28 #include <X11/Xlib.h>
29 #include "gdk.h"
30 #include "gdkprivate.h"
31
32
33 GdkGC*
34 gdk_gc_new (GdkWindow *window)
35 {
36   return gdk_gc_new_with_values (window, NULL, 0);
37 }
38
39 GdkGC*
40 gdk_gc_new_with_values (GdkWindow       *window,
41                         GdkGCValues     *values,
42                         GdkGCValuesMask  values_mask)
43 {
44   GdkWindowPrivate *window_private;
45   GdkGC *gc;
46   GdkGCPrivate *private;
47   Window xwindow;
48   XGCValues xvalues;
49   unsigned long xvalues_mask;
50
51   g_return_val_if_fail (window != NULL, NULL);
52
53   window_private = (GdkWindowPrivate*) window;
54   if (window_private->destroyed)
55     return NULL;
56
57   private = g_new (GdkGCPrivate, 1);
58   gc = (GdkGC*) private;
59
60   xwindow = window_private->xwindow;
61   private->xdisplay = window_private->xdisplay;
62   private->ref_count = 1;
63
64   xvalues.function = GXcopy;
65   xvalues.fill_style = FillSolid;
66   xvalues.arc_mode = ArcPieSlice;
67   xvalues.subwindow_mode = ClipByChildren;
68   xvalues.graphics_exposures = True;
69   xvalues_mask = GCFunction | GCFillStyle | GCArcMode | GCSubwindowMode | GCGraphicsExposures;
70
71   if (values_mask & GDK_GC_FOREGROUND)
72     {
73       xvalues.foreground = values->foreground.pixel;
74       xvalues_mask |= GCForeground;
75     }
76   if (values_mask & GDK_GC_BACKGROUND)
77     {
78       xvalues.background = values->background.pixel;
79       xvalues_mask |= GCBackground;
80     }
81   if ((values_mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
82     {
83       xvalues.font = ((XFontStruct *) ((GdkFontPrivate*) values->font)->xfont)->fid;
84       xvalues_mask |= GCFont;
85     }
86   if (values_mask & GDK_GC_FUNCTION)
87     {
88       switch (values->function)
89         {
90         case GDK_COPY:
91           xvalues.function = GXcopy;
92           break;
93         case GDK_INVERT:
94           xvalues.function = GXinvert;
95           break;
96         case GDK_XOR:
97           xvalues.function = GXxor;
98           break;
99         case GDK_CLEAR:
100           xvalues.function = GXclear;
101           break;
102         case GDK_AND:
103           xvalues.function = GXand;
104           break;
105         case GDK_AND_REVERSE:
106           xvalues.function = GXandReverse;
107           break;
108         case GDK_AND_INVERT:
109           xvalues.function = GXandInverted;
110           break;
111         case GDK_NOOP:
112           xvalues.function = GXnoop;
113           break;
114         case GDK_OR:
115           xvalues.function = GXor;
116           break;
117         case GDK_EQUIV:
118           xvalues.function = GXequiv;
119           break;
120         case GDK_OR_REVERSE:
121           xvalues.function = GXorReverse;
122           break;
123         case GDK_COPY_INVERT:
124           xvalues.function = GXcopyInverted;
125           break;
126         case GDK_OR_INVERT:
127           xvalues.function = GXorInverted;
128           break;
129         case GDK_NAND:
130           xvalues.function = GXnand;
131           break;
132         case GDK_SET:
133           xvalues.function = GXset;
134           break;
135         }
136       xvalues_mask |= GCFunction;
137     }
138   if (values_mask & GDK_GC_FILL)
139     {
140       switch (values->fill)
141         {
142         case GDK_SOLID:
143           xvalues.fill_style = FillSolid;
144           break;
145         case GDK_TILED:
146           xvalues.fill_style = FillTiled;
147           break;
148         case GDK_STIPPLED:
149           xvalues.fill_style = FillStippled;
150           break;
151         case GDK_OPAQUE_STIPPLED:
152           xvalues.fill_style = FillOpaqueStippled;
153           break;
154         }
155       xvalues_mask |= GCFillStyle;
156     }
157   if (values_mask & GDK_GC_TILE)
158     {
159       xvalues.tile = ((GdkPixmapPrivate*) values->tile)->xwindow;
160       xvalues_mask |= GCTile;
161     }
162   if (values_mask & GDK_GC_STIPPLE)
163     {
164       xvalues.stipple = ((GdkPixmapPrivate*) values->stipple)->xwindow;
165       xvalues_mask |= GCStipple;
166     }
167   if (values_mask & GDK_GC_CLIP_MASK)
168     {
169       xvalues.clip_mask = ((GdkPixmapPrivate*) values->clip_mask)->xwindow;
170       xvalues_mask |= GCClipMask;
171     }
172   if (values_mask & GDK_GC_SUBWINDOW)
173     {
174       xvalues.subwindow_mode = values->subwindow_mode;
175       xvalues_mask |= GCSubwindowMode;
176     }
177   if (values_mask & GDK_GC_TS_X_ORIGIN)
178     {
179       xvalues.ts_x_origin = values->ts_x_origin;
180       xvalues_mask |= GCTileStipXOrigin;
181     }
182   if (values_mask & GDK_GC_TS_Y_ORIGIN)
183     {
184       xvalues.ts_y_origin = values->ts_y_origin;
185       xvalues_mask |= GCTileStipYOrigin;
186     }
187   if (values_mask & GDK_GC_CLIP_X_ORIGIN)
188     {
189       xvalues.clip_x_origin = values->clip_x_origin;
190       xvalues_mask |= GCClipXOrigin;
191     }
192   if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
193     {
194       xvalues.clip_y_origin = values->clip_y_origin;
195       xvalues_mask |= GCClipYOrigin;
196     }
197  
198   if (values_mask & GDK_GC_EXPOSURES)
199     xvalues.graphics_exposures = values->graphics_exposures;
200   else
201     xvalues.graphics_exposures = False;
202   xvalues_mask |= GCGraphicsExposures;
203
204   if (values_mask & GDK_GC_LINE_WIDTH)
205     {
206       xvalues.line_width = values->line_width;
207       xvalues_mask |= GCLineWidth;
208     }
209   if (values_mask & GDK_GC_LINE_STYLE)
210     {
211       switch (values->line_style)
212         {
213         case GDK_LINE_SOLID:
214           xvalues.line_style = LineSolid;
215           break;
216         case GDK_LINE_ON_OFF_DASH:
217           xvalues.line_style = LineOnOffDash;
218           break;
219         case GDK_LINE_DOUBLE_DASH:
220           xvalues.line_style = LineDoubleDash;
221           break;
222         }
223       xvalues_mask |= GCLineStyle;
224     }
225   if (values_mask & GDK_GC_CAP_STYLE)
226     {
227       switch (values->cap_style)
228         {
229         case GDK_CAP_NOT_LAST:
230           xvalues.cap_style = CapNotLast;
231           break;
232         case GDK_CAP_BUTT:
233           xvalues.cap_style = CapButt;
234           break;
235         case GDK_CAP_ROUND:
236           xvalues.cap_style = CapRound;
237           break;
238         case GDK_CAP_PROJECTING:
239           xvalues.cap_style = CapProjecting;
240           break;
241         }
242       xvalues_mask |= GCCapStyle;
243     }
244   if (values_mask & GDK_GC_JOIN_STYLE)
245     {
246       switch (values->join_style)
247         {
248         case GDK_JOIN_MITER:
249           xvalues.join_style = JoinMiter;
250           break;
251         case GDK_JOIN_ROUND:
252           xvalues.join_style = JoinRound;
253           break;
254         case GDK_JOIN_BEVEL:
255           xvalues.join_style = JoinBevel;
256           break;
257         }
258       xvalues_mask |= GCJoinStyle;
259     }
260
261   private->xgc = XCreateGC (private->xdisplay, xwindow, xvalues_mask, &xvalues);
262
263   return gc;
264 }
265
266 void
267 gdk_gc_destroy (GdkGC *gc)
268 {
269   gdk_gc_unref (gc);
270 }
271
272 GdkGC *
273 gdk_gc_ref (GdkGC *gc)
274 {
275   GdkGCPrivate *private = (GdkGCPrivate*) gc;
276
277   g_return_val_if_fail (gc != NULL, NULL);
278   private->ref_count += 1;
279
280   return gc;
281 }
282
283 void
284 gdk_gc_unref (GdkGC *gc)
285 {
286   GdkGCPrivate *private = (GdkGCPrivate*) gc;
287   
288   g_return_if_fail (gc != NULL);
289   g_return_if_fail (private->ref_count > 0);
290   
291   if (private->ref_count > 1)
292     private->ref_count -= 1;
293   else
294     {
295       XFreeGC (private->xdisplay, private->xgc);
296       memset (gc, 0, sizeof (GdkGCPrivate));
297       g_free (gc);
298     }
299 }
300
301 void
302 gdk_gc_get_values (GdkGC       *gc,
303                    GdkGCValues *values)
304 {
305   GdkGCPrivate *private;
306   XGCValues xvalues;
307
308   g_return_if_fail (gc != NULL);
309   g_return_if_fail (values != NULL);
310
311   private = (GdkGCPrivate*) gc;
312
313   if (XGetGCValues (private->xdisplay, private->xgc,
314                     GCForeground | GCBackground | GCFont |
315                     GCFunction | GCTile | GCStipple | /* GCClipMask | */
316                     GCSubwindowMode | GCGraphicsExposures |
317                     GCTileStipXOrigin | GCTileStipYOrigin |
318                     GCClipXOrigin | GCClipYOrigin |
319                     GCLineWidth | GCLineStyle | GCCapStyle |
320                     GCFillStyle | GCJoinStyle, &xvalues))
321     {
322       values->foreground.pixel = xvalues.foreground;
323       values->background.pixel = xvalues.background;
324       values->font = gdk_font_lookup (xvalues.font);
325
326       switch (xvalues.function)
327         {
328         case GXcopy:
329           values->function = GDK_COPY;
330           break;
331         case GXinvert:
332           values->function = GDK_INVERT;
333           break;
334         case GXxor:
335           values->function = GDK_XOR;
336           break;
337         case GXclear:
338           values->function = GDK_CLEAR;
339           break;
340         case GXand:
341           values->function = GDK_AND;
342           break;
343         case GXandReverse:
344           values->function = GDK_AND_REVERSE;
345           break;
346         case GXandInverted:
347           values->function = GDK_AND_INVERT;
348           break;
349         case GXnoop:
350           values->function = GDK_NOOP;
351           break;
352         case GXor:
353           values->function = GDK_OR;
354           break;
355         case GXequiv:
356           values->function = GDK_EQUIV;
357           break;
358         case GXorReverse:
359           values->function = GDK_OR_REVERSE;
360           break;
361         case GXcopyInverted:
362           values->function =GDK_COPY_INVERT;
363           break;
364         case GXorInverted:
365           values->function = GDK_OR_INVERT;
366           break;
367         case GXnand:
368           values->function = GDK_NAND;
369           break;
370         case GXset:
371           values->function = GDK_SET;
372           break;
373         }
374
375       switch (xvalues.fill_style)
376         {
377         case FillSolid:
378           values->fill = GDK_SOLID;
379           break;
380         case FillTiled:
381           values->fill = GDK_TILED;
382           break;
383         case FillStippled:
384           values->fill = GDK_STIPPLED;
385           break;
386         case FillOpaqueStippled:
387           values->fill = GDK_OPAQUE_STIPPLED;
388           break;
389         }
390
391       values->tile = gdk_pixmap_lookup (xvalues.tile);
392       values->stipple = gdk_pixmap_lookup (xvalues.stipple);
393       values->clip_mask = NULL;
394       values->subwindow_mode = xvalues.subwindow_mode;
395       values->ts_x_origin = xvalues.ts_x_origin;
396       values->ts_y_origin = xvalues.ts_y_origin;
397       values->clip_x_origin = xvalues.clip_x_origin;
398       values->clip_y_origin = xvalues.clip_y_origin;
399       values->graphics_exposures = xvalues.graphics_exposures;
400       values->line_width = xvalues.line_width;
401
402       switch (xvalues.line_style)
403         {
404         case LineSolid:
405           values->line_style = GDK_LINE_SOLID;
406           break;
407         case LineOnOffDash:
408           values->line_style = GDK_LINE_ON_OFF_DASH;
409           break;
410         case LineDoubleDash:
411           values->line_style = GDK_LINE_DOUBLE_DASH;
412           break;
413         }
414
415       switch (xvalues.cap_style)
416         {
417         case CapNotLast:
418           values->cap_style = GDK_CAP_NOT_LAST;
419           break;
420         case CapButt:
421           values->cap_style = GDK_CAP_BUTT;
422           break;
423         case CapRound:
424           values->cap_style = GDK_CAP_ROUND;
425           break;
426         case CapProjecting:
427           values->cap_style = GDK_CAP_PROJECTING;
428           break;
429         }
430
431       switch (xvalues.join_style)
432         {
433         case JoinMiter:
434           values->join_style = GDK_JOIN_MITER;
435           break;
436         case JoinRound:
437           values->join_style = GDK_JOIN_ROUND;
438           break;
439         case JoinBevel:
440           values->join_style = GDK_JOIN_BEVEL;
441           break;
442         }
443     }
444   else
445     {
446       memset (values, 0, sizeof (GdkGCValues));
447     }
448 }
449
450 void
451 gdk_gc_set_foreground (GdkGC    *gc,
452                        GdkColor *color)
453 {
454   GdkGCPrivate *private;
455
456   g_return_if_fail (gc != NULL);
457   g_return_if_fail (color != NULL);
458
459   private = (GdkGCPrivate*) gc;
460   XSetForeground (private->xdisplay, private->xgc, color->pixel);
461 }
462
463 void
464 gdk_gc_set_background (GdkGC    *gc,
465                        GdkColor *color)
466 {
467   GdkGCPrivate *private;
468
469   g_return_if_fail (gc != NULL);
470   g_return_if_fail (color != NULL);
471
472   private = (GdkGCPrivate*) gc;
473   XSetBackground (private->xdisplay, private->xgc, color->pixel);
474 }
475
476 void
477 gdk_gc_set_font (GdkGC   *gc,
478                  GdkFont *font)
479 {
480   GdkGCPrivate *gc_private;
481   GdkFontPrivate *font_private;
482
483   g_return_if_fail (gc != NULL);
484   g_return_if_fail (font != NULL);
485
486   if (font->type == GDK_FONT_FONT)
487     {
488       gc_private = (GdkGCPrivate*) gc;
489       font_private = (GdkFontPrivate*) font;
490       
491       XSetFont (gc_private->xdisplay, gc_private->xgc,
492                 ((XFontStruct *) font_private->xfont)->fid);
493     }
494 }
495
496 void
497 gdk_gc_set_function (GdkGC       *gc,
498                      GdkFunction  function)
499 {
500   GdkGCPrivate *private;
501
502   g_return_if_fail (gc != NULL);
503
504   private = (GdkGCPrivate*) gc;
505
506   switch (function)
507     {
508     case GDK_COPY:
509       XSetFunction (private->xdisplay, private->xgc, GXcopy);
510       break;
511     case GDK_INVERT:
512       XSetFunction (private->xdisplay, private->xgc, GXinvert);
513       break;
514     case GDK_XOR:
515       XSetFunction (private->xdisplay, private->xgc, GXxor);
516       break;
517     case GDK_CLEAR:
518       XSetFunction (private->xdisplay, private->xgc, GXclear);
519       break;
520     case GDK_AND:
521       XSetFunction (private->xdisplay, private->xgc, GXand);
522       break;
523     case GDK_AND_REVERSE:
524       XSetFunction (private->xdisplay, private->xgc, GXandReverse);
525       break;
526     case GDK_AND_INVERT:
527       XSetFunction (private->xdisplay, private->xgc, GXandInverted);
528       break;
529     case GDK_NOOP:
530       XSetFunction (private->xdisplay, private->xgc, GXnoop);
531       break;
532     case GDK_OR:
533       XSetFunction (private->xdisplay, private->xgc, GXor);
534       break;
535     case GDK_EQUIV:
536       XSetFunction (private->xdisplay, private->xgc, GXequiv);
537       break;
538     case GDK_OR_REVERSE:
539       XSetFunction (private->xdisplay, private->xgc, GXorReverse);
540       break;
541     case GDK_COPY_INVERT:
542       XSetFunction (private->xdisplay, private->xgc, GXcopyInverted);
543       break;
544     case GDK_OR_INVERT:
545       XSetFunction (private->xdisplay, private->xgc, GXorInverted);
546       break;
547     case GDK_NAND:
548       XSetFunction (private->xdisplay, private->xgc, GXnand);
549       break;
550     case GDK_SET:
551       XSetFunction (private->xdisplay, private->xgc, GXset);
552       break;
553     }
554 }
555
556 void
557 gdk_gc_set_fill (GdkGC   *gc,
558                  GdkFill  fill)
559 {
560   GdkGCPrivate *private;
561
562   g_return_if_fail (gc != NULL);
563
564   private = (GdkGCPrivate*) gc;
565
566   switch (fill)
567     {
568     case GDK_SOLID:
569       XSetFillStyle (private->xdisplay, private->xgc, FillSolid);
570       break;
571     case GDK_TILED:
572       XSetFillStyle (private->xdisplay, private->xgc, FillTiled);
573       break;
574     case GDK_STIPPLED:
575       XSetFillStyle (private->xdisplay, private->xgc, FillStippled);
576       break;
577     case GDK_OPAQUE_STIPPLED:
578       XSetFillStyle (private->xdisplay, private->xgc, FillOpaqueStippled);
579       break;
580     }
581 }
582
583 void
584 gdk_gc_set_tile (GdkGC     *gc,
585                  GdkPixmap *tile)
586 {
587   GdkGCPrivate *private;
588   GdkPixmapPrivate *pixmap_private;
589   Pixmap pixmap;
590
591   g_return_if_fail (gc != NULL);
592
593   private = (GdkGCPrivate*) gc;
594
595   pixmap = None;
596   if (tile)
597     {
598       pixmap_private = (GdkPixmapPrivate*) tile;
599       pixmap = pixmap_private->xwindow;
600     }
601
602   XSetTile (private->xdisplay, private->xgc, pixmap);
603 }
604
605 void
606 gdk_gc_set_stipple (GdkGC     *gc,
607                     GdkPixmap *stipple)
608 {
609   GdkGCPrivate *private;
610   GdkPixmapPrivate *pixmap_private;
611   Pixmap pixmap;
612
613   g_return_if_fail (gc != NULL);
614
615   private = (GdkGCPrivate*) gc;
616
617   pixmap = None;
618   if (stipple)
619     {
620       pixmap_private = (GdkPixmapPrivate*) stipple;
621       pixmap = pixmap_private->xwindow;
622     }
623
624   XSetStipple (private->xdisplay, private->xgc, pixmap);
625 }
626
627 void
628 gdk_gc_set_ts_origin (GdkGC *gc,
629                       gint   x,
630                       gint   y)
631 {
632   GdkGCPrivate *private;
633
634   g_return_if_fail (gc != NULL);
635
636   private = (GdkGCPrivate*) gc;
637
638   XSetTSOrigin (private->xdisplay, private->xgc, x, y);
639 }
640
641 void
642 gdk_gc_set_clip_origin (GdkGC *gc,
643                         gint   x,
644                         gint   y)
645 {
646   GdkGCPrivate *private;
647
648   g_return_if_fail (gc != NULL);
649
650   private = (GdkGCPrivate*) gc;
651
652   XSetClipOrigin (private->xdisplay, private->xgc, x, y);
653 }
654
655 void
656 gdk_gc_set_clip_mask (GdkGC     *gc,
657                       GdkBitmap *mask)
658 {
659   GdkGCPrivate *private;
660   Pixmap xmask;
661   
662   g_return_if_fail (gc != NULL);
663   
664   if (mask)
665     {
666       GdkWindowPrivate *mask_private;
667       
668       mask_private = (GdkWindowPrivate*) mask;
669       if (mask_private->destroyed)
670         return;
671       xmask = mask_private->xwindow;
672     }
673   else
674     xmask = None;
675   
676   private = (GdkGCPrivate*) gc;
677
678   XSetClipMask (private->xdisplay, private->xgc, xmask);
679 }
680
681
682 void
683 gdk_gc_set_clip_rectangle (GdkGC        *gc,
684                            GdkRectangle *rectangle)
685 {
686   GdkGCPrivate *private;
687   XRectangle xrectangle;
688    
689   g_return_if_fail (gc != NULL);
690
691   private = (GdkGCPrivate*) gc;
692
693   if (rectangle)
694     {
695       xrectangle.x = rectangle->x; 
696       xrectangle.y = rectangle->y;
697       xrectangle.width = rectangle->width;
698       xrectangle.height = rectangle->height;
699       
700       XSetClipRectangles (private->xdisplay, private->xgc, 0, 0,
701                           &xrectangle, 1, Unsorted);
702     }
703   else
704     XSetClipMask (private->xdisplay, private->xgc, None);
705
706
707 void
708 gdk_gc_set_clip_region (GdkGC            *gc,
709                         GdkRegion        *region)
710 {
711   GdkGCPrivate *private;
712
713   g_return_if_fail (gc != NULL);
714
715   private = (GdkGCPrivate*) gc;
716
717   if (region)
718     {
719       GdkRegionPrivate *region_private;
720
721       region_private = (GdkRegionPrivate*) region;
722       XSetRegion (private->xdisplay, private->xgc, region_private->xregion);
723     }
724   else
725     XSetClipMask (private->xdisplay, private->xgc, None);
726 }
727
728 void
729 gdk_gc_set_subwindow (GdkGC            *gc,
730                       GdkSubwindowMode  mode)
731 {
732   GdkGCPrivate *private;
733
734   g_return_if_fail (gc != NULL);
735
736   private = (GdkGCPrivate*) gc;
737
738   XSetSubwindowMode (private->xdisplay, private->xgc, mode);
739 }
740
741 void
742 gdk_gc_set_exposures (GdkGC *gc,
743                       gint   exposures)
744 {
745   GdkGCPrivate *private;
746
747   g_return_if_fail (gc != NULL);
748
749   private = (GdkGCPrivate*) gc;
750
751   XSetGraphicsExposures (private->xdisplay, private->xgc, exposures);
752 }
753
754 void
755 gdk_gc_set_line_attributes (GdkGC       *gc,
756                             gint         line_width,
757                             GdkLineStyle line_style,
758                             GdkCapStyle  cap_style,
759                             GdkJoinStyle join_style)
760 {
761   GdkGCPrivate *private;
762   int xline_style;
763   int xcap_style;
764   int xjoin_style;
765
766   g_return_if_fail (gc != NULL);
767
768   private = (GdkGCPrivate*) gc;
769
770   switch (line_style)
771     {
772     case GDK_LINE_SOLID:
773       xline_style = LineSolid;
774       break;
775     case GDK_LINE_ON_OFF_DASH:
776       xline_style = LineOnOffDash;
777       break;
778     case GDK_LINE_DOUBLE_DASH:
779       xline_style = LineDoubleDash;
780       break;
781     default:
782       xline_style = None;
783     }
784
785   switch (cap_style)
786     {
787     case GDK_CAP_NOT_LAST:
788       xcap_style = CapNotLast;
789       break;
790     case GDK_CAP_BUTT:
791       xcap_style = CapButt;
792       break;
793     case GDK_CAP_ROUND:
794       xcap_style = CapRound;
795       break;
796     case GDK_CAP_PROJECTING:
797       xcap_style = CapProjecting;
798       break;
799     default:
800       xcap_style = None;
801     }
802
803   switch (join_style)
804     {
805     case GDK_JOIN_MITER:
806       xjoin_style = JoinMiter;
807       break;
808     case GDK_JOIN_ROUND:
809       xjoin_style = JoinRound;
810       break;
811     case GDK_JOIN_BEVEL:
812       xjoin_style = JoinBevel;
813       break;
814     default:
815       xjoin_style = None;
816     }
817
818   XSetLineAttributes (private->xdisplay, private->xgc, line_width,
819                       xline_style, xcap_style, xjoin_style);
820 }
821
822 void
823 gdk_gc_set_dashes (GdkGC *gc,
824                    gint   dash_offset,
825                    gchar  dash_list[],
826                    gint   n)
827 {
828   GdkGCPrivate *private;
829
830   g_return_if_fail (gc != NULL);
831   g_return_if_fail (dash_list != NULL);
832
833   private = (GdkGCPrivate*) gc;
834
835   XSetDashes (private->xdisplay, private->xgc, dash_offset, dash_list, n);
836 }
837
838 void
839 gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
840 {
841   GdkGCPrivate *dst_private, *src_private;
842
843   src_private = (GdkGCPrivate *) src_gc;
844   dst_private = (GdkGCPrivate *) dst_gc;
845
846   XCopyGC (src_private->xdisplay, src_private->xgc, ~((~1) << GCLastBit),
847            dst_private->xgc);
848 }