]> Pileus Git - ~andy/gtk/blob - gdk/gdkgc.c
Handle Control-digits specially.
[~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   
290   if (private->ref_count > 1)
291     private->ref_count -= 1;
292   else
293     {
294       XFreeGC (private->xdisplay, private->xgc);
295       memset (gc, 0, sizeof (GdkGCPrivate));
296       g_free (gc);
297     }
298 }
299
300 void
301 gdk_gc_get_values (GdkGC       *gc,
302                    GdkGCValues *values)
303 {
304   GdkGCPrivate *private;
305   XGCValues xvalues;
306
307   g_return_if_fail (gc != NULL);
308   g_return_if_fail (values != NULL);
309
310   private = (GdkGCPrivate*) gc;
311
312   if (XGetGCValues (private->xdisplay, private->xgc,
313                     GCForeground | GCBackground | GCFont |
314                     GCFunction | GCTile | GCStipple | /* GCClipMask | */
315                     GCSubwindowMode | GCGraphicsExposures |
316                     GCTileStipXOrigin | GCTileStipYOrigin |
317                     GCClipXOrigin | GCClipYOrigin |
318                     GCLineWidth | GCLineStyle | GCCapStyle |
319                     GCFillStyle | GCJoinStyle, &xvalues))
320     {
321       values->foreground.pixel = xvalues.foreground;
322       values->background.pixel = xvalues.background;
323       values->font = gdk_font_lookup (xvalues.font);
324
325       switch (xvalues.function)
326         {
327         case GXcopy:
328           values->function = GDK_COPY;
329           break;
330         case GXinvert:
331           values->function = GDK_INVERT;
332           break;
333         case GXxor:
334           values->function = GDK_XOR;
335           break;
336         case GXclear:
337           values->function = GDK_CLEAR;
338           break;
339         case GXand:
340           values->function = GDK_AND;
341           break;
342         case GXandReverse:
343           values->function = GDK_AND_REVERSE;
344           break;
345         case GXandInverted:
346           values->function = GDK_AND_INVERT;
347           break;
348         case GXnoop:
349           values->function = GDK_NOOP;
350           break;
351         case GXor:
352           values->function = GDK_OR;
353           break;
354         case GXequiv:
355           values->function = GDK_EQUIV;
356           break;
357         case GXorReverse:
358           values->function = GDK_OR_REVERSE;
359           break;
360         case GXcopyInverted:
361           values->function =GDK_COPY_INVERT;
362           break;
363         case GXorInverted:
364           values->function = GDK_OR_INVERT;
365           break;
366         case GXnand:
367           values->function = GDK_NAND;
368           break;
369         case GXset:
370           values->function = GDK_SET;
371           break;
372         }
373
374       switch (xvalues.fill_style)
375         {
376         case FillSolid:
377           values->fill = GDK_SOLID;
378           break;
379         case FillTiled:
380           values->fill = GDK_TILED;
381           break;
382         case FillStippled:
383           values->fill = GDK_STIPPLED;
384           break;
385         case FillOpaqueStippled:
386           values->fill = GDK_OPAQUE_STIPPLED;
387           break;
388         }
389
390       values->tile = gdk_pixmap_lookup (xvalues.tile);
391       values->stipple = gdk_pixmap_lookup (xvalues.stipple);
392       values->clip_mask = NULL;
393       values->subwindow_mode = xvalues.subwindow_mode;
394       values->ts_x_origin = xvalues.ts_x_origin;
395       values->ts_y_origin = xvalues.ts_y_origin;
396       values->clip_x_origin = xvalues.clip_x_origin;
397       values->clip_y_origin = xvalues.clip_y_origin;
398       values->graphics_exposures = xvalues.graphics_exposures;
399       values->line_width = xvalues.line_width;
400
401       switch (xvalues.line_style)
402         {
403         case LineSolid:
404           values->line_style = GDK_LINE_SOLID;
405           break;
406         case LineOnOffDash:
407           values->line_style = GDK_LINE_ON_OFF_DASH;
408           break;
409         case LineDoubleDash:
410           values->line_style = GDK_LINE_DOUBLE_DASH;
411           break;
412         }
413
414       switch (xvalues.cap_style)
415         {
416         case CapNotLast:
417           values->cap_style = GDK_CAP_NOT_LAST;
418           break;
419         case CapButt:
420           values->cap_style = GDK_CAP_BUTT;
421           break;
422         case CapRound:
423           values->cap_style = GDK_CAP_ROUND;
424           break;
425         case CapProjecting:
426           values->cap_style = GDK_CAP_PROJECTING;
427           break;
428         }
429
430       switch (xvalues.join_style)
431         {
432         case JoinMiter:
433           values->join_style = GDK_JOIN_MITER;
434           break;
435         case JoinRound:
436           values->join_style = GDK_JOIN_ROUND;
437           break;
438         case JoinBevel:
439           values->join_style = GDK_JOIN_BEVEL;
440           break;
441         }
442     }
443   else
444     {
445       memset (values, 0, sizeof (GdkGCValues));
446     }
447 }
448
449 void
450 gdk_gc_set_foreground (GdkGC    *gc,
451                        GdkColor *color)
452 {
453   GdkGCPrivate *private;
454
455   g_return_if_fail (gc != NULL);
456   g_return_if_fail (color != NULL);
457
458   private = (GdkGCPrivate*) gc;
459   XSetForeground (private->xdisplay, private->xgc, color->pixel);
460 }
461
462 void
463 gdk_gc_set_background (GdkGC    *gc,
464                        GdkColor *color)
465 {
466   GdkGCPrivate *private;
467
468   g_return_if_fail (gc != NULL);
469   g_return_if_fail (color != NULL);
470
471   private = (GdkGCPrivate*) gc;
472   XSetBackground (private->xdisplay, private->xgc, color->pixel);
473 }
474
475 void
476 gdk_gc_set_font (GdkGC   *gc,
477                  GdkFont *font)
478 {
479   GdkGCPrivate *gc_private;
480   GdkFontPrivate *font_private;
481
482   g_return_if_fail (gc != NULL);
483   g_return_if_fail (font != NULL);
484
485   if (font->type == GDK_FONT_FONT)
486     {
487       gc_private = (GdkGCPrivate*) gc;
488       font_private = (GdkFontPrivate*) font;
489       
490       XSetFont (gc_private->xdisplay, gc_private->xgc,
491                 ((XFontStruct *) font_private->xfont)->fid);
492     }
493 }
494
495 void
496 gdk_gc_set_function (GdkGC       *gc,
497                      GdkFunction  function)
498 {
499   GdkGCPrivate *private;
500
501   g_return_if_fail (gc != NULL);
502
503   private = (GdkGCPrivate*) gc;
504
505   switch (function)
506     {
507     case GDK_COPY:
508       XSetFunction (private->xdisplay, private->xgc, GXcopy);
509       break;
510     case GDK_INVERT:
511       XSetFunction (private->xdisplay, private->xgc, GXinvert);
512       break;
513     case GDK_XOR:
514       XSetFunction (private->xdisplay, private->xgc, GXxor);
515       break;
516     case GDK_CLEAR:
517       XSetFunction (private->xdisplay, private->xgc, GXclear);
518       break;
519     case GDK_AND:
520       XSetFunction (private->xdisplay, private->xgc, GXand);
521       break;
522     case GDK_AND_REVERSE:
523       XSetFunction (private->xdisplay, private->xgc, GXandReverse);
524       break;
525     case GDK_AND_INVERT:
526       XSetFunction (private->xdisplay, private->xgc, GXandInverted);
527       break;
528     case GDK_NOOP:
529       XSetFunction (private->xdisplay, private->xgc, GXnoop);
530       break;
531     case GDK_OR:
532       XSetFunction (private->xdisplay, private->xgc, GXor);
533       break;
534     case GDK_EQUIV:
535       XSetFunction (private->xdisplay, private->xgc, GXequiv);
536       break;
537     case GDK_OR_REVERSE:
538       XSetFunction (private->xdisplay, private->xgc, GXorReverse);
539       break;
540     case GDK_COPY_INVERT:
541       XSetFunction (private->xdisplay, private->xgc, GXcopyInverted);
542       break;
543     case GDK_OR_INVERT:
544       XSetFunction (private->xdisplay, private->xgc, GXorInverted);
545       break;
546     case GDK_NAND:
547       XSetFunction (private->xdisplay, private->xgc, GXnand);
548       break;
549     case GDK_SET:
550       XSetFunction (private->xdisplay, private->xgc, GXset);
551       break;
552     }
553 }
554
555 void
556 gdk_gc_set_fill (GdkGC   *gc,
557                  GdkFill  fill)
558 {
559   GdkGCPrivate *private;
560
561   g_return_if_fail (gc != NULL);
562
563   private = (GdkGCPrivate*) gc;
564
565   switch (fill)
566     {
567     case GDK_SOLID:
568       XSetFillStyle (private->xdisplay, private->xgc, FillSolid);
569       break;
570     case GDK_TILED:
571       XSetFillStyle (private->xdisplay, private->xgc, FillTiled);
572       break;
573     case GDK_STIPPLED:
574       XSetFillStyle (private->xdisplay, private->xgc, FillStippled);
575       break;
576     case GDK_OPAQUE_STIPPLED:
577       XSetFillStyle (private->xdisplay, private->xgc, FillOpaqueStippled);
578       break;
579     }
580 }
581
582 void
583 gdk_gc_set_tile (GdkGC     *gc,
584                  GdkPixmap *tile)
585 {
586   GdkGCPrivate *private;
587   GdkPixmapPrivate *pixmap_private;
588   Pixmap pixmap;
589
590   g_return_if_fail (gc != NULL);
591
592   private = (GdkGCPrivate*) gc;
593
594   pixmap = None;
595   if (tile)
596     {
597       pixmap_private = (GdkPixmapPrivate*) tile;
598       pixmap = pixmap_private->xwindow;
599     }
600
601   XSetTile (private->xdisplay, private->xgc, pixmap);
602 }
603
604 void
605 gdk_gc_set_stipple (GdkGC     *gc,
606                     GdkPixmap *stipple)
607 {
608   GdkGCPrivate *private;
609   GdkPixmapPrivate *pixmap_private;
610   Pixmap pixmap;
611
612   g_return_if_fail (gc != NULL);
613
614   private = (GdkGCPrivate*) gc;
615
616   pixmap = None;
617   if (stipple)
618     {
619       pixmap_private = (GdkPixmapPrivate*) stipple;
620       pixmap = pixmap_private->xwindow;
621     }
622
623   XSetStipple (private->xdisplay, private->xgc, pixmap);
624 }
625
626 void
627 gdk_gc_set_ts_origin (GdkGC *gc,
628                       gint   x,
629                       gint   y)
630 {
631   GdkGCPrivate *private;
632
633   g_return_if_fail (gc != NULL);
634
635   private = (GdkGCPrivate*) gc;
636
637   XSetTSOrigin (private->xdisplay, private->xgc, x, y);
638 }
639
640 void
641 gdk_gc_set_clip_origin (GdkGC *gc,
642                         gint   x,
643                         gint   y)
644 {
645   GdkGCPrivate *private;
646
647   g_return_if_fail (gc != NULL);
648
649   private = (GdkGCPrivate*) gc;
650
651   XSetClipOrigin (private->xdisplay, private->xgc, x, y);
652 }
653
654 void
655 gdk_gc_set_clip_mask (GdkGC     *gc,
656                       GdkBitmap *mask)
657 {
658   GdkGCPrivate *private;
659   Pixmap xmask;
660   
661   g_return_if_fail (gc != NULL);
662   
663   if (mask)
664     {
665       GdkWindowPrivate *mask_private;
666       
667       mask_private = (GdkWindowPrivate*) mask;
668       if (mask_private->destroyed)
669         return;
670       xmask = mask_private->xwindow;
671     }
672   else
673     xmask = None;
674   
675   private = (GdkGCPrivate*) gc;
676
677   XSetClipMask (private->xdisplay, private->xgc, xmask);
678 }
679
680
681 void
682 gdk_gc_set_clip_rectangle (GdkGC        *gc,
683                            GdkRectangle *rectangle)
684 {
685   GdkGCPrivate *private;
686   XRectangle xrectangle;
687    
688   g_return_if_fail (gc != NULL);
689
690   private = (GdkGCPrivate*) gc;
691
692   if (rectangle)
693     {
694       xrectangle.x = rectangle->x; 
695       xrectangle.y = rectangle->y;
696       xrectangle.width = rectangle->width;
697       xrectangle.height = rectangle->height;
698       
699       XSetClipRectangles (private->xdisplay, private->xgc, 0, 0,
700                           &xrectangle, 1, Unsorted);
701     }
702   else
703     XSetClipMask (private->xdisplay, private->xgc, None);
704
705
706 void
707 gdk_gc_set_clip_region (GdkGC            *gc,
708                         GdkRegion        *region)
709 {
710   GdkGCPrivate *private;
711
712   g_return_if_fail (gc != NULL);
713
714   private = (GdkGCPrivate*) gc;
715
716   if (region)
717     {
718       GdkRegionPrivate *region_private;
719
720       region_private = (GdkRegionPrivate*) region;
721       XSetRegion (private->xdisplay, private->xgc, region_private->xregion);
722     }
723   else
724     XSetClipMask (private->xdisplay, private->xgc, None);
725 }
726
727 void
728 gdk_gc_set_subwindow (GdkGC            *gc,
729                       GdkSubwindowMode  mode)
730 {
731   GdkGCPrivate *private;
732
733   g_return_if_fail (gc != NULL);
734
735   private = (GdkGCPrivate*) gc;
736
737   XSetSubwindowMode (private->xdisplay, private->xgc, mode);
738 }
739
740 void
741 gdk_gc_set_exposures (GdkGC *gc,
742                       gint   exposures)
743 {
744   GdkGCPrivate *private;
745
746   g_return_if_fail (gc != NULL);
747
748   private = (GdkGCPrivate*) gc;
749
750   XSetGraphicsExposures (private->xdisplay, private->xgc, exposures);
751 }
752
753 void
754 gdk_gc_set_line_attributes (GdkGC       *gc,
755                             gint         line_width,
756                             GdkLineStyle line_style,
757                             GdkCapStyle  cap_style,
758                             GdkJoinStyle join_style)
759 {
760   GdkGCPrivate *private;
761   int xline_style;
762   int xcap_style;
763   int xjoin_style;
764
765   g_return_if_fail (gc != NULL);
766
767   private = (GdkGCPrivate*) gc;
768
769   switch (line_style)
770     {
771     case GDK_LINE_SOLID:
772       xline_style = LineSolid;
773       break;
774     case GDK_LINE_ON_OFF_DASH:
775       xline_style = LineOnOffDash;
776       break;
777     case GDK_LINE_DOUBLE_DASH:
778       xline_style = LineDoubleDash;
779       break;
780     default:
781       xline_style = None;
782     }
783
784   switch (cap_style)
785     {
786     case GDK_CAP_NOT_LAST:
787       xcap_style = CapNotLast;
788       break;
789     case GDK_CAP_BUTT:
790       xcap_style = CapButt;
791       break;
792     case GDK_CAP_ROUND:
793       xcap_style = CapRound;
794       break;
795     case GDK_CAP_PROJECTING:
796       xcap_style = CapProjecting;
797       break;
798     default:
799       xcap_style = None;
800     }
801
802   switch (join_style)
803     {
804     case GDK_JOIN_MITER:
805       xjoin_style = JoinMiter;
806       break;
807     case GDK_JOIN_ROUND:
808       xjoin_style = JoinRound;
809       break;
810     case GDK_JOIN_BEVEL:
811       xjoin_style = JoinBevel;
812       break;
813     default:
814       xjoin_style = None;
815     }
816
817   XSetLineAttributes (private->xdisplay, private->xgc, line_width,
818                       xline_style, xcap_style, xjoin_style);
819 }
820
821 void
822 gdk_gc_set_dashes (GdkGC *gc,
823                    gint   dash_offset,
824                    gchar  dash_list[],
825                    gint   n)
826 {
827   GdkGCPrivate *private;
828
829   g_return_if_fail (gc != NULL);
830   g_return_if_fail (dash_list != NULL);
831
832   private = (GdkGCPrivate*) gc;
833
834   XSetDashes (private->xdisplay, private->xgc, dash_offset, dash_list, n);
835 }
836
837 void
838 gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
839 {
840   GdkGCPrivate *dst_private, *src_private;
841
842   src_private = (GdkGCPrivate *) src_gc;
843   dst_private = (GdkGCPrivate *) dst_gc;
844
845   XCopyGC (src_private->xdisplay, src_private->xgc, ~((~1) << GCLastBit),
846            dst_private->xgc);
847 }