]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkdrawable-win32.c
Add new keysyms from X11R6.4 (including EuroSign).
[~andy/gtk] / gdk / win32 / gdkdrawable-win32.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 "config.h"
28
29 #include <math.h>
30
31 #include "gdkdrawable.h"
32 #include "gdkprivate.h"
33 #include "gdkwindow.h"
34 #include "gdkx.h"
35
36 #ifndef G_PI
37 #define G_PI 3.14159265358979323846
38 #endif
39
40 /* Manipulation of drawables
41  */
42 void          
43 gdk_drawable_set_data (GdkDrawable   *drawable,
44                        const gchar   *key,
45                        gpointer       data,
46                        GDestroyNotify destroy_func)
47 {
48   g_dataset_set_data_full (drawable, key, data, destroy_func);
49 }
50
51 void          
52 gdk_drawable_get_data (GdkDrawable   *drawable,
53                        const gchar   *key)
54 {
55   g_dataset_get_data (drawable, key);
56 }
57
58 GdkDrawableType
59 gdk_drawable_get_type (GdkDrawable *drawable)
60 {
61   g_return_val_if_fail (drawable != NULL, (GdkDrawableType) -1);
62   
63   return GDK_DRAWABLE_TYPE (drawable);
64 }
65
66 void
67 gdk_drawable_get_size (GdkDrawable *drawable,
68                        gint        *width,
69                        gint        *height)
70 {
71   GdkDrawablePrivate *drawable_private;
72   
73   g_return_if_fail (drawable != NULL);
74   
75   drawable_private = (GdkDrawablePrivate*) drawable;
76   
77   if (width)
78     *width = drawable_private->width;
79   if (height)
80     *height = drawable_private->height;
81 }
82
83 void
84 gdk_drawable_set_colormap (GdkDrawable *drawable,
85                            GdkColormap *colormap)
86 {
87   GdkDrawablePrivate *drawable_private;
88   GdkColormapPrivate *colormap_private;
89   
90   g_return_if_fail (drawable != NULL);
91   g_return_if_fail (colormap != NULL);
92   
93   drawable_private = (GdkDrawablePrivate*) drawable;
94   colormap_private = (GdkColormapPrivate*) colormap;
95   
96   if (!GDK_DRAWABLE_DESTROYED (drawable))
97     {
98       if (GDK_IS_WINDOW (drawable))
99         {
100           g_return_if_fail (colormap_private->visual !=
101                             ((GdkColormapPrivate*)(drawable_private->colormap))->visual);
102           /* XXX ??? */
103           GDK_NOTE (MISC, g_print ("gdk_drawable_set_colormap: %#x %#x\n",
104                                    GDK_DRAWABLE_XID (drawable),
105                                    colormap_private->xcolormap));
106         }
107       if (drawable_private->colormap)
108         gdk_colormap_unref (drawable_private->colormap);
109       drawable_private->colormap = colormap;
110       gdk_colormap_ref (drawable_private->colormap);
111       
112       if (GDK_IS_WINDOW (drawable) &&
113           drawable_private->window_type != GDK_WINDOW_TOPLEVEL)
114         gdk_window_add_colormap_windows (drawable);
115     }
116 }
117
118 GdkColormap*
119 gdk_drawable_get_colormap (GdkDrawable *drawable)
120 {
121   GdkDrawablePrivate *drawable_private;
122   
123   g_return_val_if_fail (drawable != NULL, NULL);
124   drawable_private = (GdkDrawablePrivate*) drawable;
125
126   if (!GDK_DRAWABLE_DESTROYED (drawable))
127     {
128       if (drawable_private->colormap == NULL)
129         return gdk_colormap_get_system (); /* XXX ??? */
130       else
131         return drawable_private->colormap;
132     }
133   
134   return NULL;
135 }
136
137 GdkVisual*
138 gdk_drawable_get_visual (GdkDrawable *drawable)
139 {
140   GdkColormap *colormap;
141
142   g_return_val_if_fail (drawable != NULL, NULL);
143
144   colormap = gdk_drawable_get_colormap (drawable);
145   return colormap ? gdk_colormap_get_visual (colormap) : NULL;
146 }
147
148 void
149 gdk_draw_point (GdkDrawable *drawable,
150                 GdkGC       *gc,
151                 gint         x,
152                 gint         y)
153 {
154   GdkDrawablePrivate *drawable_private;
155   GdkGCPrivate *gc_private;
156   HDC hdc;
157
158   g_return_if_fail (drawable != NULL);
159   g_return_if_fail (gc != NULL);
160
161   if (GDK_DRAWABLE_DESTROYED (drawable))
162     return;
163   drawable_private = (GdkDrawablePrivate*) drawable;
164   gc_private = (GdkGCPrivate*) gc;
165
166   hdc = gdk_gc_predraw (drawable_private, gc_private);
167
168   /* We use LineTo because SetPixel wants the COLORREF directly,
169    * and doesn't use the current pen, which is what we want.
170    */
171   if (!MoveToEx (hdc, x, y, NULL))
172     g_warning ("gdk_draw_point: MoveToEx failed");
173   if (!LineTo (hdc, x + 1, y))
174     g_warning ("gdk_draw_point: LineTo failed");
175   
176   gdk_gc_postdraw (drawable_private, gc_private);
177 }
178
179 void
180 gdk_draw_line (GdkDrawable *drawable,
181                GdkGC       *gc,
182                gint         x1,
183                gint         y1,
184                gint         x2,
185                gint         y2)
186 {
187   GdkDrawablePrivate *drawable_private;
188   GdkGCPrivate *gc_private;
189   HDC hdc;
190
191   g_return_if_fail (drawable != NULL);
192   g_return_if_fail (gc != NULL);
193
194   if (GDK_DRAWABLE_DESTROYED (drawable))
195     return;
196   drawable_private = (GdkDrawablePrivate*) drawable;
197   gc_private = (GdkGCPrivate*) gc;
198
199   hdc = gdk_gc_predraw (drawable_private, gc_private);
200     
201   GDK_NOTE (MISC, g_print ("gdk_draw_line: %#x (%d) +%d+%d..+%d+%d\n",
202                            drawable_private->xwindow, gc_private,
203                            x1, y1, x2, y2));
204   
205   MoveToEx (hdc, x1, y1, NULL);
206   if (!LineTo (hdc, x2, y2))
207     g_warning ("gdk_draw_line: LineTo #1 failed");
208   /* LineTo doesn't draw the last point, so if we have a pen width of 1,
209    * we draw the end pixel separately... With wider pens we don't care.
210    * //HB: But the NT developers don't read their API documentation ...
211    */
212   if (gc_private->pen_width == 1
213       && GetVersion () > 0x80000000)
214     if (!LineTo (hdc, x2 + 1, y2))
215       g_warning ("gdk_draw_line: LineTo #2 failed");
216   gdk_gc_postdraw (drawable_private, gc_private);
217 }
218
219 void
220 gdk_draw_rectangle (GdkDrawable *drawable,
221                     GdkGC       *gc,
222                     gint         filled,
223                     gint         x,
224                     gint         y,
225                     gint         width,
226                     gint         height)
227 {
228   GdkDrawablePrivate *drawable_private;
229   GdkGCPrivate *gc_private;
230   HDC hdc;
231   HGDIOBJ oldpen, oldbrush;
232
233   g_return_if_fail (drawable != NULL);
234   g_return_if_fail (gc != NULL);
235
236   if (GDK_DRAWABLE_DESTROYED (drawable))
237     return;
238   drawable_private = (GdkDrawablePrivate*) drawable;
239   gc_private = (GdkGCPrivate*) gc;
240
241   if (width == -1)
242     width = drawable_private->width;
243   if (height == -1)
244     height = drawable_private->height;
245
246   hdc = gdk_gc_predraw (drawable_private, gc_private);
247
248   GDK_NOTE (MISC, g_print ("gdk_draw_rectangle: %#x (%d) %s%dx%d@+%d+%d\n",
249                            drawable_private->xwindow,
250                            gc_private,
251                            (filled ? "fill " : ""),
252                            width, height, x, y));
253     
254 #if 0
255   {
256     HBRUSH hbr = GetCurrentObject (hdc, OBJ_BRUSH);
257     HPEN hpen = GetCurrentObject (hdc, OBJ_PEN);
258     LOGBRUSH lbr;
259     LOGPEN lpen;
260     GetObject (hbr, sizeof (lbr), &lbr);
261     GetObject (hpen, sizeof (lpen), &lpen);
262     
263     g_print ("current brush: style = %s, color = 0x%.08x\n",
264              (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"),
265              lbr.lbColor);
266     g_print ("current pen: style = %s, width = %d, color = 0x%.08x\n",
267              (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"),
268              lpen.lopnWidth,
269              lpen.lopnColor);
270   }
271 #endif
272
273   if (filled)
274     oldpen = SelectObject (hdc, GetStockObject (NULL_PEN));
275   else
276     oldbrush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH));
277   
278   if (!Rectangle (hdc, x, y, x+width+1, y+height+1))
279     g_warning ("gdk_draw_rectangle: Rectangle failed");
280   
281   if (filled)
282     SelectObject (hdc, oldpen);
283   else
284     SelectObject (hdc, oldbrush);
285
286   gdk_gc_postdraw (drawable_private, gc_private);
287 }
288
289 void
290 gdk_draw_arc (GdkDrawable *drawable,
291               GdkGC       *gc,
292               gint         filled,
293               gint         x,
294               gint         y,
295               gint         width,
296               gint         height,
297               gint         angle1,
298               gint         angle2)
299 {
300   GdkDrawablePrivate *drawable_private;
301   GdkGCPrivate *gc_private;
302   HDC hdc;
303   int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
304
305   g_return_if_fail (drawable != NULL);
306   g_return_if_fail (gc != NULL);
307
308   if (GDK_DRAWABLE_DESTROYED (drawable))
309     return;
310   drawable_private = (GdkDrawablePrivate*) drawable;
311   gc_private = (GdkGCPrivate*) gc;
312
313   if (width == -1)
314     width = drawable_private->width;
315   if (height == -1)
316     height = drawable_private->height;
317
318   GDK_NOTE (MISC, g_print ("gdk_draw_arc: %#x  %d,%d,%d,%d  %d %d\n",
319                            drawable_private->xwindow,
320                            x, y, width, height, angle1, angle2));
321
322   if (width != 0 && height != 0 && angle2 != 0)
323     {
324       hdc = gdk_gc_predraw (drawable_private, gc_private);
325
326       if (angle2 >= 360*64)
327         {
328           nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0;
329         }
330       else if (angle2 > 0)
331         {
332           /* The 100. is just an arbitrary value */
333           nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
334           nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
335           nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
336           nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
337         }
338       else
339         {
340           nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.);
341           nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.);
342           nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.);
343           nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.);
344         }
345
346       if (filled)
347         {
348           GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
349                                    x, y, x+width, y+height,
350                                    nXStartArc, nYStartArc,
351                                    nXEndArc, nYEndArc));
352           Pie (hdc, x, y, x+width, y+height,
353                nXStartArc, nYStartArc, nXEndArc, nYEndArc);
354         }
355       else
356         {
357           GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
358                                    x, y, x+width, y+height,
359                                    nXStartArc, nYStartArc,
360                                    nXEndArc, nYEndArc));
361           Arc (hdc, x, y, x+width, y+height,
362                nXStartArc, nYStartArc, nXEndArc, nYEndArc);
363         }
364       gdk_gc_postdraw (drawable_private, gc_private);
365     }
366 }
367
368 void
369 gdk_draw_polygon (GdkDrawable *drawable,
370                   GdkGC       *gc,
371                   gint         filled,
372                   GdkPoint    *points,
373                   gint         npoints)
374 {
375   GdkDrawablePrivate *drawable_private;
376   GdkGCPrivate *gc_private;
377   HDC hdc;
378   POINT *pts;
379   int i;
380
381   g_return_if_fail (drawable != NULL);
382   g_return_if_fail (gc != NULL);
383
384   if (GDK_DRAWABLE_DESTROYED (drawable))
385     return;
386   drawable_private = (GdkDrawablePrivate*) drawable;
387   gc_private = (GdkGCPrivate*) gc;
388
389   GDK_NOTE (MISC, g_print ("gdk_draw_polygon: %#x (%d) %d\n",
390                            drawable_private->xwindow, gc_private,
391                            npoints));
392
393   if (npoints < 2)
394     return;
395
396   hdc = gdk_gc_predraw (drawable_private, gc_private);
397   pts = g_malloc ((npoints+1) * sizeof (POINT));
398
399   for (i = 0; i < npoints; i++)
400     {
401       pts[i].x = points[i].x;
402       pts[i].y = points[i].y;
403     }
404   
405   if ((points[0].x != points[npoints-1].x) ||
406       (points[0].y != points[npoints-1].y)) 
407     {
408       pts[npoints].x = points[0].x;
409       pts[npoints].y = points[0].y;
410       npoints++;
411     }
412   if (filled)
413     {
414       if (!Polygon (hdc, pts, npoints))
415         g_warning ("gdk_draw_polygon: Polygon failed");
416     }
417   else
418     {
419       if (!Polyline (hdc, pts, npoints))
420         g_warning ("gdk_draw_polygon: Polyline failed");
421     }
422   g_free (pts);
423   gdk_gc_postdraw (drawable_private, gc_private);
424 }
425
426 /* gdk_draw_string
427  */
428 void
429 gdk_draw_string (GdkDrawable *drawable,
430                  GdkFont     *font,
431                  GdkGC       *gc,
432                  gint         x,
433                  gint         y,
434                  const gchar *string)
435 {
436   gdk_draw_text (drawable, font, gc, x, y, string, strlen (string));
437 }
438
439 /* gdk_draw_text
440  *
441  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
442  */
443 void
444 gdk_draw_text (GdkDrawable *drawable,
445                GdkFont     *font,
446                GdkGC       *gc,
447                gint         x,
448                gint         y,
449                const gchar *text,
450                gint         text_length)
451 {
452   GdkDrawablePrivate *drawable_private;
453   GdkFontPrivate *font_private;
454   GdkGCPrivate *gc_private;
455   HDC hdc;
456   HFONT xfont;
457   HGDIOBJ oldfont;
458   wchar_t *wcstr;
459   gint wlen;
460
461   g_return_if_fail (drawable != NULL);
462   g_return_if_fail (font != NULL);
463   g_return_if_fail (gc != NULL);
464   g_return_if_fail (text != NULL);
465
466   if (GDK_DRAWABLE_DESTROYED (drawable))
467     return;
468
469   if (text_length == 0)
470     return;
471
472   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
473
474   drawable_private = (GdkDrawablePrivate*) drawable;
475   gc_private = (GdkGCPrivate*) gc;
476   font_private = (GdkFontPrivate*) font;
477
478   hdc = gdk_gc_predraw (drawable_private, gc_private);
479   xfont = (HFONT) font_private->xfont;
480
481   GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
482                            "+%d+%d font: %#x \"%.*s\" length: %d\n",
483                            drawable_private->xwindow,
484                            gc_private, gc_private->xgc,
485                            x, y, xfont,
486                            (text_length > 10 ? 10 : text_length),
487                            text, text_length));
488   
489   if ((oldfont = SelectObject (hdc, xfont)) == NULL)
490     g_warning ("gdk_draw_text: SelectObject failed");
491
492   wcstr = g_new (wchar_t, text_length);
493   if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
494     g_warning ("gdk_draw_text: gdk_nmbstowchar_ts failed");
495   else if (!TextOutW (hdc, x, y, wcstr, wlen))
496     g_warning ("gdk_draw_text: TextOutW failed");
497   g_free (wcstr);
498   if (oldfont != NULL)
499     SelectObject (hdc, oldfont);
500   gdk_gc_postdraw (drawable_private, gc_private);
501 }
502
503 void
504 gdk_draw_text_wc (GdkDrawable    *drawable,
505                   GdkFont        *font,
506                   GdkGC          *gc,
507                   gint            x,
508                   gint            y,
509                   const GdkWChar *text,
510                   gint            text_length)
511 {
512   HDC hdc;
513   HGDIOBJ oldfont;
514   GdkDrawablePrivate *drawable_private;
515   GdkFontPrivate *font_private;
516   GdkGCPrivate *gc_private;
517   gint i, wlen;
518   wchar_t *wcstr;
519   guchar *str;
520
521   g_return_if_fail (drawable != NULL);
522   g_return_if_fail (font != NULL);
523   g_return_if_fail (gc != NULL);
524   g_return_if_fail (text != NULL);
525
526   if (GDK_DRAWABLE_DESTROYED (drawable))
527     return;
528
529   if (text_length == 0)
530     return;
531
532   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
533
534   drawable_private = (GdkDrawablePrivate*) drawable;
535   gc_private = (GdkGCPrivate*) gc;
536   font_private = (GdkFontPrivate*) font;
537
538   hdc = gdk_gc_predraw (drawable_private, gc_private);
539
540   GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
541                            "+%d+%d font: %#x length: %d\n",
542                            drawable_private->xwindow,
543                            gc_private, gc_private->xgc,
544                            x, y, font_private->xfont,
545                            text_length));
546       
547   if ((oldfont = SelectObject (hdc, font_private->xfont)) == NULL)
548     g_warning ("gdk_draw_text_wc: SelectObject failed");
549   if (sizeof (wchar_t) != sizeof (GdkWChar))
550     {
551       wcstr = g_new (wchar_t, text_length);
552       for (i = 0; i < text_length; i++)
553         wcstr[i] = text[i];
554     }
555   else
556     wcstr = (wchar_t *) text;
557
558   if (!TextOutW (hdc, x, y, wcstr, text_length))
559     g_warning ("gdk_draw_text_wc: TextOutW failed");
560
561   if (sizeof (wchar_t) != sizeof (GdkWChar))
562     g_free (wcstr);
563   if (oldfont != NULL)
564     SelectObject (hdc, oldfont);
565   gdk_gc_postdraw (drawable_private, gc_private);
566 }
567
568 void
569 gdk_draw_pixmap (GdkDrawable *drawable,
570                  GdkGC       *gc,
571                  GdkPixmap   *src,
572                  gint         xsrc,
573                  gint         ysrc,
574                  gint         xdest,
575                  gint         ydest,
576                  gint         width,
577                  gint         height)
578 {
579   GdkDrawablePrivate *drawable_private;
580   GdkDrawablePrivate *src_private;
581   GdkGCPrivate *gc_private;
582   HDC hdc;
583   HDC srcdc;
584   HGDIOBJ hgdiobj;
585   HRGN src_rgn, draw_rgn, outside_rgn;
586   RECT r;
587
588   g_return_if_fail (drawable != NULL);
589   g_return_if_fail (src != NULL);
590   g_return_if_fail (gc != NULL);
591
592   if (GDK_DRAWABLE_DESTROYED (drawable) || GDK_DRAWABLE_DESTROYED (src))
593     return;
594   drawable_private = (GdkDrawablePrivate*) drawable;
595   src_private = (GdkDrawablePrivate*) src;
596   gc_private = (GdkGCPrivate*) gc;
597
598   if (width == -1)
599     width = src_private->width; /* Or should we subtract xsrc? */
600   if (height == -1)
601     height = src_private->height; /* Ditto? */
602
603   GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x "
604                            "src: %#x %dx%d@+%d+%d"
605                            " dest: %#x @+%d+%d\n",
606                            drawable_private->xwindow,
607                            src_private->xwindow,
608                            width, height, xsrc, ysrc,
609                            drawable_private->xwindow, xdest, ydest));
610
611   hdc = gdk_gc_predraw (drawable_private, gc_private);
612
613   src_rgn = CreateRectRgn (0, 0, src_private->width + 1, src_private->height + 1);
614   draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1);
615   SetRectEmpty (&r);
616   outside_rgn = CreateRectRgnIndirect (&r);
617   
618   if (drawable_private->window_type != GDK_DRAWABLE_PIXMAP)
619     {
620       /* If we are drawing on a window, calculate the region that is
621        * outside the source pixmap, and invalidate that, causing it to
622        * be cleared. XXX
623        */
624       if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION)
625         {
626           OffsetRgn (outside_rgn, xdest, ydest);
627           GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r),
628                            g_print ("...calling InvalidateRgn, "
629                                     "bbox: %dx%d@+%d+%d\n",
630                                     r.right - r.left - 1, r.bottom - r.top - 1,
631                                     r.left, r.top)));
632           InvalidateRgn (drawable_private->xwindow, outside_rgn, TRUE);
633         }
634     }
635
636 #if 1 /* Don't know if this is necessary  */
637   if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
638     g_warning ("gdk_draw_pixmap: CombineRgn returned a COMPLEXREGION");
639
640   GetRgnBox (draw_rgn, &r);
641   if (r.left != xsrc
642       || r.top != ysrc
643       || r.right != xsrc + width + 1
644       || r.bottom != ysrc + height + 1)
645     {
646       xdest += r.left - xsrc;
647       xsrc = r.left;
648       ydest += r.top - ysrc;
649       ysrc = r.top;
650       width = r.right - xsrc - 1;
651       height = r.bottom - ysrc - 1;
652       
653       GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, "
654                                "dest: @+%d+%d\n",
655                                width, height, xsrc, ysrc,
656                                xdest, ydest));
657     }
658 #endif
659
660   DeleteObject (src_rgn);
661   DeleteObject (draw_rgn);
662   DeleteObject (outside_rgn);
663
664   /* Strangely enough, this function is called also to bitblt
665    * from a window.
666    */
667   if (src_private->window_type == GDK_DRAWABLE_PIXMAP)
668     {
669       if ((srcdc = CreateCompatibleDC (hdc)) == NULL)
670         g_warning ("gdk_draw_pixmap: CreateCompatibleDC failed");
671       
672       if ((hgdiobj = SelectObject (srcdc, src_private->xwindow)) == NULL)
673         g_warning ("gdk_draw_pixmap: SelectObject #1 failed");
674       
675       if (!BitBlt (hdc, xdest, ydest, width, height,
676                    srcdc, xsrc, ysrc, SRCCOPY))
677         g_warning ("gdk_draw_pixmap: BitBlt failed");
678       
679       if ((SelectObject (srcdc, hgdiobj) == NULL))
680         g_warning ("gdk_draw_pixmap: SelectObject #2 failed");
681       
682       if (!DeleteDC (srcdc))
683         g_warning ("gdk_draw_pixmap: DeleteDC failed");
684     }
685   else
686     {
687       if (drawable_private->xwindow == src_private->xwindow)
688         {
689           /* Blitting inside a window, use ScrollDC */
690           RECT scrollRect, clipRect, emptyRect;
691           HRGN updateRgn;
692
693           scrollRect.left = MIN (xsrc, xdest);
694           scrollRect.top = MIN (ysrc, ydest);
695           scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1);
696           scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1);
697
698           clipRect.left = xdest;
699           clipRect.top = ydest;
700           clipRect.right = xdest + width + 1;
701           clipRect.bottom = ydest + height + 1;
702
703           SetRectEmpty (&emptyRect);
704           updateRgn = CreateRectRgnIndirect (&emptyRect);
705           if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc,
706                          &scrollRect, &clipRect,
707                          updateRgn, NULL))
708             g_warning ("gdk_draw_pixmap: ScrollDC failed");
709           if (!InvalidateRgn (drawable_private->xwindow, updateRgn, FALSE))
710             g_warning ("gdk_draw_pixmap: InvalidateRgn failed");
711           if (!UpdateWindow (drawable_private->xwindow))
712             g_warning ("gdk_draw_pixmap: UpdateWindow failed");
713         }
714       else
715         {
716           if ((srcdc = GetDC (src_private->xwindow)) == NULL)
717             g_warning ("gdk_draw_pixmap: GetDC failed");
718           
719           if (!BitBlt (hdc, xdest, ydest, width, height,
720                        srcdc, xsrc, ysrc, SRCCOPY))
721             g_warning ("gdk_draw_pixmap: BitBlt failed");
722           ReleaseDC (src_private->xwindow, srcdc);
723         }
724     }
725   gdk_gc_postdraw (drawable_private, gc_private);
726 }
727
728 void
729 gdk_draw_image (GdkDrawable *drawable,
730                 GdkGC       *gc,
731                 GdkImage    *image,
732                 gint         xsrc,
733                 gint         ysrc,
734                 gint         xdest,
735                 gint         ydest,
736                 gint         width,
737                 gint         height)
738 {
739   GdkImagePrivate *image_private;
740
741   g_return_if_fail (drawable != NULL);
742   g_return_if_fail (image != NULL);
743   g_return_if_fail (gc != NULL);
744
745   image_private = (GdkImagePrivate*) image;
746
747   g_return_if_fail (image_private->image_put != NULL);
748
749   if (width == -1)
750     width = image->width;
751   if (height == -1)
752     height = image->height;
753
754   (* image_private->image_put) (drawable, gc, image, xsrc, ysrc,
755                                 xdest, ydest, width, height);
756 }
757
758 void
759 gdk_draw_points (GdkDrawable *drawable,
760                  GdkGC       *gc,
761                  GdkPoint    *points,
762                  gint         npoints)
763 {
764   GdkDrawablePrivate *drawable_private;
765   GdkGCPrivate *gc_private;
766   HDC hdc;
767   int i;
768
769   g_return_if_fail (drawable != NULL);
770   g_return_if_fail ((points != NULL) && (npoints > 0));
771   g_return_if_fail (gc != NULL);
772
773   if (GDK_DRAWABLE_DESTROYED (drawable))
774     return;
775   drawable_private = (GdkDrawablePrivate*) drawable;
776   gc_private = (GdkGCPrivate*) gc;
777
778   hdc = gdk_gc_predraw (drawable_private, gc_private);
779   
780   GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x destdc: (%d) %#x "
781                            "npoints: %d\n",
782                            drawable_private->xwindow, gc_private, hdc,
783                            npoints));
784
785   for (i = 0; i < npoints; i++)
786     {
787       if (!MoveToEx (hdc, points[i].x, points[i].y, NULL))
788         g_warning ("gdk_draw_points: MoveToEx failed");
789       if (!LineTo (hdc, points[i].x + 1, points[i].y))
790         g_warning ("gdk_draw_points: LineTo failed");
791     }
792   gdk_gc_postdraw (drawable_private, gc_private);
793 }
794
795 void
796 gdk_draw_segments (GdkDrawable *drawable,
797                    GdkGC       *gc,
798                    GdkSegment  *segs,
799                    gint         nsegs)
800 {
801   GdkDrawablePrivate *drawable_private;
802   GdkGCPrivate *gc_private;
803   HDC hdc;
804   int i;
805
806   if (nsegs <= 0)
807     return;
808
809   g_return_if_fail (drawable != NULL);
810   g_return_if_fail (segs != NULL);
811   g_return_if_fail (gc != NULL);
812
813   if (GDK_DRAWABLE_DESTROYED (drawable))
814     return;
815   drawable_private = (GdkDrawablePrivate*) drawable;
816   gc_private = (GdkGCPrivate*) gc;
817
818   hdc = gdk_gc_predraw (drawable_private, gc_private);
819
820   for (i = 0; i < nsegs; i++)
821     {
822       if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL))
823         g_warning ("gdk_draw_segments: MoveToEx failed");
824       if (!LineTo (hdc, segs[i].x2, segs[i].y2))
825         g_warning ("gdk_draw_segments: LineTo #1 failed");
826       
827       /* Draw end pixel */
828       if (gc_private->pen_width == 1)
829         if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2))
830           g_warning ("gdk_draw_segments: LineTo #2 failed");
831     }
832   gdk_gc_postdraw (drawable_private, gc_private);
833 }
834
835 void
836 gdk_draw_lines (GdkDrawable *drawable,
837                 GdkGC       *gc,
838                 GdkPoint    *points,
839                 gint         npoints)
840 {
841   GdkDrawablePrivate *drawable_private;
842   GdkGCPrivate *gc_private;
843   HDC hdc;
844   POINT *pts;
845   int i;
846
847   if (npoints < 2)
848     return;
849
850   g_return_if_fail (drawable != NULL);
851   g_return_if_fail (points != NULL);
852   g_return_if_fail (gc != NULL);
853
854   if (GDK_DRAWABLE_DESTROYED (drawable))
855     return;
856   drawable_private = (GdkDrawablePrivate*) drawable;
857   gc_private = (GdkGCPrivate*) gc;
858
859   hdc = gdk_gc_predraw (drawable_private, gc_private);
860 #if 1
861   pts = g_malloc (npoints * sizeof (POINT));
862
863   for (i = 0; i < npoints; i++)
864     {
865       pts[i].x = points[i].x;
866       pts[i].y = points[i].y;
867     }
868   
869   if (!Polyline (hdc, pts, npoints))
870     g_warning ("gdk_draw_lines: Polyline(,,%d) failed", npoints);
871   
872   g_free (pts);
873   
874   /* Draw end pixel */
875   if (gc_private->pen_width == 1)
876     {
877       MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL);
878       if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
879         g_warning ("gdk_draw_lines: LineTo failed");
880     }
881 #else
882   MoveToEx (hdc, points[0].x, points[0].y, NULL);
883   for (i = 1; i < npoints; i++)
884     if (!LineTo (hdc, points[i].x, points[i].y))
885       g_warning ("gdk_draw_lines: LineTo #1 failed");
886   
887   /* Draw end pixel */
888   if (gc_private->pen_width == 1)
889     if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y))
890       g_warning ("gdk_draw_lines: LineTo #2 failed");
891 #endif  
892   gdk_gc_postdraw (drawable_private, gc_private);
893 }