aboutsummaryrefslogtreecommitdiff
path: root/win
diff options
context:
space:
mode:
authorlecoanet2003-04-16 10:11:38 +0000
committerlecoanet2003-04-16 10:11:38 +0000
commitbe9279836d090eeb1196c31583fe2a5b596c2473 (patch)
tree385391afe441ea4de88d0e210222401b6e94b01d /win
parent422c6c2fb29fde51e8907285491ec3bc2ac9d97a (diff)
downloadtkzinc-be9279836d090eeb1196c31583fe2a5b596c2473.zip
tkzinc-be9279836d090eeb1196c31583fe2a5b596c2473.tar.gz
tkzinc-be9279836d090eeb1196c31583fe2a5b596c2473.tar.bz2
tkzinc-be9279836d090eeb1196c31583fe2a5b596c2473.tar.xz
*** empty log message ***
Diffstat (limited to 'win')
-rw-r--r--win/WinPort.c1011
-rw-r--r--win/makefile.vc178
2 files changed, 1189 insertions, 0 deletions
diff --git a/win/WinPort.c b/win/WinPort.c
new file mode 100644
index 0000000..9187c57
--- /dev/null
+++ b/win/WinPort.c
@@ -0,0 +1,1011 @@
+/*
+ * WinPort.c -- Compatibility layer for Windows 2k
+ *
+ * Authors : Patrick Lecoanet.
+ * Creation date :
+ *
+ * $Id$
+ */
+
+/*
+ * Copyright (c) 2003 - CENA, Patrick Lecoanet --
+ *
+ * This code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this code; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifdef _WIN32
+
+#include "Geo.h"
+#include <tkInt.h>
+#include <tkWinInt.h>
+#include "Types.h"
+
+static const char rcsid[] = "$Id";
+static const char compile_id[]="$Compile$";
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ZnUnionRegion --
+ *
+ * Compute the union of two regions.
+ *
+ * Results:
+ * Returns the result in the dr_return region.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+ZnUnionRegion(TkRegion sra,
+ TkRegion srb,
+ TkRegion dr_return)
+{
+ CombineRgn((HRGN) dr_return, (HRGN) sra, (HRGN) srb, RGN_OR);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ZnOffsetRegion --
+ *
+ * Offset a region by the specified pixel offsets.
+ *
+ * Results:
+ * Returns the result in the dr_return region.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+ZnOffsetRegion(TkRegion reg,
+ int dx,
+ int dy)
+{
+ OffsetRgn((HRGN) reg, dx, dy);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ZnPolygonRegion --
+ *
+ * Compute a region from a polygon.
+ *
+ * Results:
+ * Returns the result in the dr_return region.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+TkRegion
+ZnPolygonRegion(XPoint *points,
+ int n,
+ int fill_rule)
+{
+ POINT *pts;
+ HRGN reg;
+ int i;
+ char msg[256];
+
+ pts = ZnMalloc(n*sizeof(POINT));
+ for (i = 0; i < n; i++, points++) {
+ pts[i].x = points->x;
+ pts[i].y = points->y;
+ }
+
+ reg = CreatePolygonRgn(pts, n,
+ fill_rule==EvenOddRule?ALTERNATE:WINDING);
+ if (!reg) {
+ sprintf(msg, "Polygon region failed: %ld, n: %d\n", GetLastError(), n);
+ OutputDebugString(msg);
+ }
+ ZnFree(pts);
+ return (TkRegion) reg;
+}
+
+#define PI 3.14159265358979
+#define XAngleToRadians(a) ((double)(a) / 64 * PI / 180);
+
+/*
+ * Translation table between X gc functions and Win32 raster op modes.
+ */
+
+int tkpWinRopModes[] = {
+ R2_BLACK, /* GXclear */
+ R2_MASKPEN, /* GXand */
+ R2_MASKPENNOT, /* GXandReverse */
+ R2_COPYPEN, /* GXcopy */
+ R2_MASKNOTPEN, /* GXandInverted */
+ R2_NOT, /* GXnoop */
+ R2_XORPEN, /* GXxor */
+ R2_MERGEPEN, /* GXor */
+ R2_NOTMERGEPEN, /* GXnor */
+ R2_NOTXORPEN, /* GXequiv */
+ R2_NOT, /* GXinvert */
+ R2_MERGEPENNOT, /* GXorReverse */
+ R2_NOTCOPYPEN, /* GXcopyInverted */
+ R2_MERGENOTPEN, /* GXorInverted */
+ R2_NOTMASKPEN, /* GXnand */
+ R2_WHITE /* GXset */
+};
+
+/*
+ * The following two raster ops are used to copy the foreground and background
+ * bits of a source pattern as defined by a stipple used as the pattern.
+ */
+
+#define COPYFG 0x00CA0749 /* dest = (pat & src) | (!pat & dst) */
+#define COPYBG 0x00AC0744 /* dest = (!pat & src) | (pat & dst) */
+
+/*
+ * The followng typedef is used to pass Windows GDI drawing functions.
+ */
+
+typedef BOOL (CALLBACK *WinDrawFunc) _ANSI_ARGS_((HDC dc,
+ CONST POINT* points, int npoints));
+
+typedef struct ThreadSpecificData {
+ POINT *winPoints; /* Array of points that is reused. */
+ int nWinPoints; /* Current size of point array. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetUpGraphicsPort --
+ *
+ * Set up the graphics port from the given GC.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The current port is adjusted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static HPEN
+SetUpGraphicsPort(gc)
+ GC gc;
+{
+ DWORD style;
+
+ if (gc->line_style == LineOnOffDash) {
+ unsigned char *p = (unsigned char *) &(gc->dashes);
+ /* pointer to the dash-list */
+
+ /*
+ * Below is a simple translation of serveral dash patterns
+ * to valid windows pen types. Far from complete,
+ * but I don't know how to do it better.
+ * Any ideas: <mailto:j.nijtmans@chello.nl>
+ */
+
+ if (p[1] && p[2]) {
+ if (!p[3] || p[4]) {
+ style = PS_DASHDOTDOT; /* -.. */
+ } else {
+ style = PS_DASHDOT; /* -. */
+ }
+ } else {
+ if (p[0] > (4 * gc->line_width)) {
+ style = PS_DASH; /* - */
+ } else {
+ style = PS_DOT; /* . */
+ }
+ }
+ } else {
+ style = PS_SOLID;
+ }
+ if (gc->line_width < 2) {
+ return CreatePen(style, gc->line_width, gc->foreground);
+ } else {
+ LOGBRUSH lb;
+
+ lb.lbStyle = BS_SOLID;
+ lb.lbColor = gc->foreground;
+ lb.lbHatch = 0;
+
+ style |= PS_GEOMETRIC;
+ switch (gc->cap_style) {
+ case CapNotLast:
+ case CapButt:
+ style |= PS_ENDCAP_FLAT;
+ break;
+ case CapRound:
+ style |= PS_ENDCAP_ROUND;
+ break;
+ default:
+ style |= PS_ENDCAP_SQUARE;
+ break;
+ }
+ switch (gc->join_style) {
+ case JoinMiter:
+ style |= PS_JOIN_MITER;
+ break;
+ case JoinRound:
+ style |= PS_JOIN_ROUND;
+ break;
+ default:
+ style |= PS_JOIN_BEVEL;
+ break;
+ }
+ return ExtCreatePen(style, gc->line_width, &lb, 0, NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConvertPoints --
+ *
+ * Convert an array of X points to an array of Win32 points.
+ *
+ * Results:
+ * Returns the converted array of POINTs.
+ *
+ * Side effects:
+ * Allocates a block of memory in thread local storage that
+ * should not be freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static POINT *
+ConvertPoints(points, npoints, mode, bbox)
+ XPoint *points;
+ int npoints;
+ int mode; /* CoordModeOrigin or CoordModePrevious. */
+ RECT *bbox; /* Bounding box of points. */
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ int i;
+
+ /*
+ * To avoid paying the cost of a malloc on every drawing routine,
+ * we reuse the last array if it is large enough.
+ */
+
+ if (npoints > tsdPtr->nWinPoints) {
+ if (tsdPtr->winPoints != NULL) {
+ ckfree((char *) tsdPtr->winPoints);
+ }
+ tsdPtr->winPoints = (POINT *) ckalloc(sizeof(POINT) * npoints);
+ if (tsdPtr->winPoints == NULL) {
+ tsdPtr->nWinPoints = -1;
+ return NULL;
+ }
+ tsdPtr->nWinPoints = npoints;
+ }
+
+ bbox->left = bbox->right = points[0].x;
+ bbox->top = bbox->bottom = points[0].y;
+
+ if (mode == CoordModeOrigin) {
+ for (i = 0; i < npoints; i++) {
+ tsdPtr->winPoints[i].x = points[i].x;
+ tsdPtr->winPoints[i].y = points[i].y;
+ bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x);
+ bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x);
+ bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y);
+ bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y);
+ }
+ } else {
+ tsdPtr->winPoints[0].x = points[0].x;
+ tsdPtr->winPoints[0].y = points[0].y;
+ for (i = 1; i < npoints; i++) {
+ tsdPtr->winPoints[i].x = tsdPtr->winPoints[i-1].x + points[i].x;
+ tsdPtr->winPoints[i].y = tsdPtr->winPoints[i-1].y + points[i].y;
+ bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x);
+ bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x);
+ bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y);
+ bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y);
+ }
+ }
+ return tsdPtr->winPoints;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillRectangles --
+ *
+ * Fill multiple rectangular areas in the given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws onto the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+XFillRectangles(display, d, gc, rectangles, nrectangles)
+ Display* display;
+ Drawable d;
+ GC gc;
+ XRectangle* rectangles;
+ int nrectangles;
+{
+ HDC dc;
+ int i;
+ RECT rect;
+ TkWinDCState state;
+ HBRUSH brush;
+ TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
+
+ if (d == None) {
+ return;
+ }
+
+ dc = TkWinGetDrawableDC(display, d, &state);
+ SetROP2(dc, tkpWinRopModes[gc->function]);
+ brush = CreateSolidBrush(gc->foreground);
+
+ if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
+ SelectClipRgn(dc, (HRGN) clipPtr->value.region);
+ OffsetClipRgn(dc, gc->clip_x_origin, gc->clip_y_origin);
+ }
+ if ((gc->fill_style == FillStippled
+ || gc->fill_style == FillOpaqueStippled)
+ && gc->stipple != None) {
+ TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
+ HBRUSH oldBrush, stipple;
+ HBITMAP oldBitmap, bitmap;
+ HDC dcMem;
+ HBRUSH bgBrush = CreateSolidBrush(gc->background);
+
+ if (twdPtr->type != TWD_BITMAP) {
+ panic("unexpected drawable type in stipple");
+ }
+
+ /*
+ * Select stipple pattern into destination dc.
+ */
+
+ stipple = CreatePatternBrush(twdPtr->bitmap.handle);
+ SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
+ oldBrush = SelectObject(dc, stipple);
+ dcMem = CreateCompatibleDC(dc);
+
+ /*
+ * For each rectangle, create a drawing surface which is the size of
+ * the rectangle and fill it with the background color. Then merge the
+ * result with the stipple pattern.
+ */
+
+ for (i = 0; i < nrectangles; i++) {
+ bitmap = CreateCompatibleBitmap(dc, rectangles[i].width,
+ rectangles[i].height);
+ oldBitmap = SelectObject(dcMem, bitmap);
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = rectangles[i].width;
+ rect.bottom = rectangles[i].height;
+ FillRect(dcMem, &rect, brush);
+ BitBlt(dc, rectangles[i].x, rectangles[i].y, rectangles[i].width,
+ rectangles[i].height, dcMem, 0, 0, COPYFG);
+ if (gc->fill_style == FillOpaqueStippled) {
+ FillRect(dcMem, &rect, bgBrush);
+ BitBlt(dc, rectangles[i].x, rectangles[i].y,
+ rectangles[i].width, rectangles[i].height, dcMem,
+ 0, 0, COPYBG);
+ }
+ SelectObject(dcMem, oldBitmap);
+ DeleteObject(bitmap);
+ }
+
+ DeleteDC(dcMem);
+ SelectObject(dc, oldBrush);
+ DeleteObject(stipple);
+ DeleteObject(bgBrush);
+ } else {
+ for (i = 0; i < nrectangles; i++) {
+ TkWinFillRect(dc, rectangles[i].x, rectangles[i].y,
+ rectangles[i].width, rectangles[i].height, gc->foreground);
+ }
+ }
+ DeleteObject(brush);
+ TkWinReleaseDrawableDC(d, dc, &state);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillRectangle --
+ *
+ * Fills a rectangular area in the given drawable. This procedure
+ * is implemented as a call to XFillRectangles.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Fills the specified rectangle.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFillRectangle(display, d, gc, x, y, width, height)
+ Display* display;
+ Drawable d;
+ GC gc;
+ int x;
+ int y;
+ unsigned int width;
+ unsigned int height;
+{
+ XRectangle rectangle;
+ rectangle.x = x;
+ rectangle.y = y;
+ rectangle.width = width;
+ rectangle.height = height;
+ XFillRectangles(display, d, gc, &rectangle, 1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RenderObject --
+ *
+ * This function draws a shape using a list of points, a
+ * stipple pattern, and the specified drawing function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RenderObject(dc, gc, points, npoints, mode, pen, func)
+ HDC dc;
+ GC gc;
+ XPoint* points;
+ int npoints;
+ int mode;
+ HPEN pen;
+ WinDrawFunc func;
+{
+ RECT rect;
+ HPEN oldPen;
+ HBRUSH oldBrush;
+ POINT *winPoints = ConvertPoints(points, npoints, mode, &rect);
+ TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
+
+ if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
+ SelectClipRgn(dc, (HRGN) clipPtr->value.region);
+ OffsetClipRgn(dc, gc->clip_x_origin, gc->clip_y_origin);
+ }
+ if ((gc->fill_style == FillStippled
+ || gc->fill_style == FillOpaqueStippled)
+ && gc->stipple != None) {
+
+ TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
+ HDC dcMem;
+ LONG width, height;
+ HBITMAP oldBitmap;
+ int i;
+ HBRUSH oldMemBrush;
+
+ if (twdPtr->type != TWD_BITMAP) {
+ panic("unexpected drawable type in stipple");
+ }
+
+ /*
+ * Grow the bounding box enough to account for line width.
+ */
+
+ rect.left -= gc->line_width;
+ rect.top -= gc->line_width;
+ rect.right += gc->line_width;
+ rect.bottom += gc->line_width;
+
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+
+ /*
+ * Select stipple pattern into destination dc.
+ */
+
+ SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
+ oldBrush = SelectObject(dc, CreatePatternBrush(twdPtr->bitmap.handle));
+
+ /*
+ * Create temporary drawing surface containing a copy of the
+ * destination equal in size to the bounding box of the object.
+ */
+
+ dcMem = CreateCompatibleDC(dc);
+ oldBitmap = SelectObject(dcMem, CreateCompatibleBitmap(dc, width,
+ height));
+ oldPen = SelectObject(dcMem, pen);
+ BitBlt(dcMem, 0, 0, width, height, dc, rect.left, rect.top, SRCCOPY);
+
+ /*
+ * Translate the object for rendering in the temporary drawing
+ * surface.
+ */
+
+ for (i = 0; i < npoints; i++) {
+ winPoints[i].x -= rect.left;
+ winPoints[i].y -= rect.top;
+ }
+
+ /*
+ * Draw the object in the foreground color and copy it to the
+ * destination wherever the pattern is set.
+ */
+
+ SetPolyFillMode(dcMem, (gc->fill_rule == EvenOddRule) ? ALTERNATE
+ : WINDING);
+ oldMemBrush = SelectObject(dcMem, CreateSolidBrush(gc->foreground));
+ (*func)(dcMem, winPoints, npoints);
+ BitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0, COPYFG);
+
+ /*
+ * If we are rendering an opaque stipple, then draw the polygon in the
+ * background color and copy it to the destination wherever the pattern
+ * is clear.
+ */
+
+ if (gc->fill_style == FillOpaqueStippled) {
+ DeleteObject(SelectObject(dcMem,
+ CreateSolidBrush(gc->background)));
+ (*func)(dcMem, winPoints, npoints);
+ BitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0,
+ COPYBG);
+ }
+
+ SelectObject(dcMem, oldPen);
+ DeleteObject(SelectObject(dcMem, oldMemBrush));
+ DeleteObject(SelectObject(dcMem, oldBitmap));
+ DeleteDC(dcMem);
+ } else {
+ oldPen = SelectObject(dc, pen);
+ oldBrush = SelectObject(dc, CreateSolidBrush(gc->foreground));
+ SetROP2(dc, tkpWinRopModes[gc->function]);
+
+ SetPolyFillMode(dc, (gc->fill_rule == EvenOddRule) ? ALTERNATE
+ : WINDING);
+
+ (*func)(dc, winPoints, npoints);
+
+ SelectObject(dc, oldPen);
+ }
+ DeleteObject(SelectObject(dc, oldBrush));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawLines --
+ *
+ * Draw connected lines.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Renders a series of connected lines.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawLines(display, d, gc, points, npoints, mode)
+ Display* display;
+ Drawable d;
+ GC gc;
+ XPoint* points;
+ int npoints;
+ int mode;
+{
+ HPEN pen;
+ TkWinDCState state;
+ HDC dc;
+ TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
+
+ if (d == None) {
+ return;
+ }
+
+ dc = TkWinGetDrawableDC(display, d, &state);
+
+ if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
+ SelectClipRgn(dc, (HRGN) clipPtr->value.region);
+ OffsetClipRgn(dc, gc->clip_x_origin, gc->clip_y_origin);
+ }
+ pen = SetUpGraphicsPort(gc);
+ SetBkMode(dc, TRANSPARENT);
+ RenderObject(dc, gc, points, npoints, mode, pen, Polyline);
+ DeleteObject(pen);
+
+ TkWinReleaseDrawableDC(d, dc, &state);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawLine --
+ *
+ * Draw a single line between two points in a given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a single line segment.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawLine(display, d, gc, x1, y1, x2, y2)
+ Display* display;
+ Drawable d;
+ GC gc;
+ int x1, y1, x2, y2; /* Coordinates of line segment. */
+{
+ XPoint points[2];
+
+ points[0].x = x1;
+ points[0].y = y1;
+ points[1].x = x2;
+ points[1].y = y2;
+ XDrawLines(display, d, gc, points, 2, CoordModeOrigin);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillPolygon --
+ *
+ * Draws a filled polygon.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a filled polygon on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFillPolygon(display, d, gc, points, npoints, shape, mode)
+ Display* display;
+ Drawable d;
+ GC gc;
+ XPoint* points;
+ int npoints;
+ int shape;
+ int mode;
+{
+ HPEN pen;
+ TkWinDCState state;
+ HDC dc;
+
+ if (d == None) {
+ return;
+ }
+
+ dc = TkWinGetDrawableDC(display, d, &state);
+
+ pen = GetStockObject(NULL_PEN);
+ RenderObject(dc, gc, points, npoints, mode, pen, Polygon);
+
+ TkWinReleaseDrawableDC(d, dc, &state);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawRectangle --
+ *
+ * Draws a rectangle.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a rectangle on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawRectangle(display, d, gc, x, y, width, height)
+ Display* display;
+ Drawable d;
+ GC gc;
+ int x;
+ int y;
+ unsigned int width;
+ unsigned int height;
+{
+ HPEN pen, oldPen;
+ TkWinDCState state;
+ HBRUSH oldBrush;
+ HDC dc;
+ TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
+
+ if (d == None) {
+ return;
+ }
+
+ dc = TkWinGetDrawableDC(display, d, &state);
+
+ if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
+ SelectClipRgn(dc, (HRGN) clipPtr->value.region);
+ OffsetClipRgn(dc, gc->clip_x_origin, gc->clip_y_origin);
+ }
+ pen = SetUpGraphicsPort(gc);
+ SetBkMode(dc, TRANSPARENT);
+ oldPen = SelectObject(dc, pen);
+ oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH));
+ SetROP2(dc, tkpWinRopModes[gc->function]);
+
+ Rectangle(dc, x, y, x+width+1, y+height+1);
+
+ DeleteObject(SelectObject(dc, oldPen));
+ SelectObject(dc, oldBrush);
+ TkWinReleaseDrawableDC(d, dc, &state);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawOrFillArc --
+ *
+ * This procedure handles the rendering of drawn or filled
+ * arcs and chords.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Renders the requested arc.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, fill)
+ Display *display;
+ Drawable d;
+ GC gc;
+ int x, y; /* left top */
+ unsigned int width, height;
+ int start; /* start: three-o'clock (deg*64) */
+ int extent; /* extent: relative (deg*64) */
+ int fill; /* ==0 draw, !=0 fill */
+{
+ HDC dc;
+ HBRUSH brush, oldBrush;
+ HPEN pen, oldPen;
+ TkWinDCState state;
+ int clockwise = (extent < 0); /* non-zero if clockwise */
+ int xstart, ystart, xend, yend;
+ double radian_start, radian_end, xr, yr;
+ TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
+
+ if (d == None) {
+ return;
+ }
+
+ dc = TkWinGetDrawableDC(display, d, &state);
+
+ if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
+ SelectClipRgn(dc, (HRGN) clipPtr->value.region);
+ OffsetClipRgn(dc, gc->clip_x_origin, gc->clip_y_origin);
+ }
+ SetROP2(dc, tkpWinRopModes[gc->function]);
+
+ /*
+ * Compute the absolute starting and ending angles in normalized radians.
+ * Swap the start and end if drawing clockwise.
+ */
+
+ start = start % (64*360);
+ if (start < 0) {
+ start += (64*360);
+ }
+ extent = (start+extent) % (64*360);
+ if (extent < 0) {
+ extent += (64*360);
+ }
+ if (clockwise) {
+ int tmp = start;
+ start = extent;
+ extent = tmp;
+ }
+ radian_start = XAngleToRadians(start);
+ radian_end = XAngleToRadians(extent);
+
+ /*
+ * Now compute points on the radial lines that define the starting and
+ * ending angles. Be sure to take into account that the y-coordinate
+ * system is inverted.
+ */
+
+ if (gc->fill_style == FillStippled && gc->stipple != None) {
+ xr = width / 2.0;
+ yr = height / 2.0;
+ }
+ else {
+ xr = x + width / 2.0;
+ yr = y + height / 2.0;
+ }
+ xstart = (int)((xr + cos(radian_start)*width/2.0) + 0.5);
+ ystart = (int)((yr + sin(-radian_start)*height/2.0) + 0.5);
+ xend = (int)((xr + cos(radian_end)*width/2.0) + 0.5);
+ yend = (int)((yr + sin(-radian_end)*height/2.0) + 0.5);
+
+ /*
+ * Now draw a filled or open figure. Note that we have to
+ * increase the size of the bounding box by one to account for the
+ * difference in pixel definitions between X and Windows.
+ */
+
+ pen = SetUpGraphicsPort(gc);
+ oldPen = SelectObject(dc, pen);
+ if (!fill) {
+ /*
+ * Note that this call will leave a gap of one pixel at the
+ * end of the arc for thin arcs. We can't use ArcTo because
+ * it's only supported under Windows NT.
+ */
+
+ SetBkMode(dc, TRANSPARENT);
+ Arc(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend);
+ } else {
+ brush = CreateSolidBrush(gc->foreground);
+
+ if (gc->fill_style == FillStippled && gc->stipple != None) {
+ TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
+ HBITMAP oldBitmap;
+ HDC dcMem;
+ HBRUSH oldMemBrush;
+
+ if (twdPtr->type != TWD_BITMAP) {
+ panic("unexpected drawable type in stipple");
+ }
+
+ /*
+ * Select stipple pattern into destination dc.
+ */
+ SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
+ oldBrush = SelectObject(dc,
+ CreatePatternBrush(twdPtr->bitmap.handle));
+
+ /*
+ * Create temporary drawing surface containing a copy of the
+ * destination equal in size to the bounding box of the object.
+ */
+ dcMem = CreateCompatibleDC(dc);
+ oldBitmap = SelectObject(dcMem,
+ CreateCompatibleBitmap(dc, width, height));
+ BitBlt(dcMem, 0, 0, width, height, dc, x, y, SRCCOPY);
+ oldMemBrush = SelectObject(dcMem, brush);
+ if (gc->arc_mode == ArcChord) {
+ Chord(dcMem, 0, 0, width+1, height+1, xstart, ystart, xend, yend);
+ } else if ( gc->arc_mode == ArcPieSlice ) {
+ Pie(dcMem, 0, 0, width+1, height+1, xstart, ystart, xend, yend);
+ }
+
+ BitBlt(dc, x, y, width, height, dcMem, 0, 0, COPYFG);
+ DeleteObject(SelectObject(dcMem, oldBitmap));
+ DeleteObject(SelectObject(dcMem, oldMemBrush));
+ DeleteObject(SelectObject(dc, oldBrush));
+ DeleteDC(dcMem);
+ } else {
+ oldBrush = SelectObject(dc, brush);
+ if (gc->arc_mode == ArcChord) {
+ Chord(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend);
+ } else if ( gc->arc_mode == ArcPieSlice ) {
+ Pie(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend);
+ }
+ DeleteObject(SelectObject(dc, oldBrush));
+ }
+ }
+ DeleteObject(SelectObject(dc, oldPen));
+ TkWinReleaseDrawableDC(d, dc, &state);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawArc --
+ *
+ * Draw an arc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws an arc on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawArc(display, d, gc, x, y, width, height, start, extent)
+ Display* display;
+ Drawable d;
+ GC gc;
+ int x;
+ int y;
+ unsigned int width;
+ unsigned int height;
+ int start;
+ int extent;
+{
+ display->request++;
+
+ DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillArc --
+ *
+ * Draw a filled arc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a filled arc on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFillArc(display, d, gc, x, y, width, height, start, extent)
+ Display* display;
+ Drawable d;
+ GC gc;
+ int x;
+ int y;
+ unsigned int width;
+ unsigned int height;
+ int start;
+ int extent;
+{
+ display->request++;
+
+ DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, 1);
+}
+
+#endif /* _WIN32 */
diff --git a/win/makefile.vc b/win/makefile.vc
new file mode 100644
index 0000000..2d21adc
--- /dev/null
+++ b/win/makefile.vc
@@ -0,0 +1,178 @@
+# Generated automatically from Makefile.in by configure.
+# Copyright (c) 1993 - 2002 CENA, Patrick Lecoanet --
+#
+# This code is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this code; if not, write to the Free
+# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Revision$
+#
+srcdir = .
+
+SHELL = /bin/sh
+
+# Visual Studio 6 default
+TOOLS32 = C:\Progra~1\Microsoft Visual Studio\VC98
+CC = "$(TOOLS32)\bin\cl.exe"
+LD = "$(TOOLS32)\bin\link.exe" -link50compat
+libpath32 = /LIBPATH:"$(TOOLS32)\lib"
+include32 = /I"$(TOOLS32)\include"
+CP = copy
+RM = del
+
+PERLCONFIG = INSTALLDIRS=perl
+
+INSTALL_PERL = install_perl
+
+prefix = c:\lecoanet
+exec_prefix = $(prefix)
+
+bindir = $(exec_prefix)\bin
+libdir = $(exec_prefix)\lib
+incdir = $(prefix)\include
+mandir = $(prefix)\man\man3
+
+windir = $(srcdir)\win
+genericdir = $(srcdir)
+tktmpdir = $(srcdir)\tkwin
+ptktmpdir = $(srcdir)\ptkwin
+
+tcl_inc_dir = $(prefix)\tcl8.4.1
+tk_inc_dir = $(prefix)\tk8.4.1
+INCLUDES = /I$(srcdir) $(include32)
+
+TCL_TK_VER = 84
+# Assume that WISH is already INSTALLED
+TCLSH = $(bindir)\tclsh$(TCL_TK_VER)
+WISH = $(bindir)\wish$(TCL_TK_VER)
+WIN_LIBS = glu32.lib user32.lib gdi32.lib ws2_32.lib
+#GL_LIBS =
+GL_LIBS = opengl32.lib
+PTKROOT = c:\perl\site\lib
+TKLIBS = $(libdir)\tcl$(TCL_TK_VER).lib \
+ $(libdir)\tk$(TCL_TK_VER).lib \
+ $(GL_LIBS) $(WIN_LIBS)
+PTKLIBS = $(PTKROOT)\auto\Tk\Tk.lib $(GL_LIBS) $(WIN_LIBS)
+
+ZINC_VER = 3
+ZINC_MAJOR = 2
+
+#
+# Recognized compilation time flags are :
+#
+# PROFILE ask for profile support
+# OM include code for internal overlap manager
+# GL include code that need GL support.
+# GL_PRINT_CONFIG display the detected hardware capabilities
+# GL_DAMAGE redraw only modified areas
+# SHAPE include code for reshaping windows.
+#
+DFLAGS= /DOM /DGL /DGL_DAMAGE /DGL_PRINT_CONFIG
+#DFLAGS= /DOM
+#DFLAGS = /DTCL_MEM_DEBUG
+
+# Max speed
+#CDEBUG = -O2 -Gs
+# Debug
+CDEBUG = -Z7 -Od
+CFLAGS = /c /W3 /nologo /YX $(CDEBUG) /DWIN /DDLL_BUILD /DBUILD_Tkzinc $(DFLAGS)
+TKCPPFLAGS = /Fp$(tktmpdir)\ $(INCLUDES) /I"$(incdir)" /I$(tk_inc_dir)\generic /I$(tk_inc_dir)\win /I$(tcl_inc_dir)\generic /I$(tcl_inc_dir)\win
+PTKCPPFLAGS = /DPTK /Fp$(ptktmpdir)\ $(INCLUDES) /I$(PTKROOT)\Tk\pTk /I$(PTKROOT)\Tk
+
+LFLAGS = /nologo /machine:IX86 /warn:3 $(libpath32)
+DLLENTRY = @12
+DLLLFLAGS = $(LFLAGS) /entry:_DllMainCRTStartup$(DLLENTRY) /dll
+
+TKDLLOBJS = $(tktmpdir)\Track.obj \
+ $(tktmpdir)\Tabular.obj \
+ $(tktmpdir)\Reticle.obj \
+ $(tktmpdir)\Map.obj \
+ $(tktmpdir)\Rectangle.obj \
+ $(tktmpdir)\Arc.obj \
+ $(tktmpdir)\Curve.obj \
+ $(tktmpdir)\Item.obj \
+# $(tktmpdir)\PostScript.obj \
+ $(tktmpdir)\MapInfo.obj \
+ $(tktmpdir)\Attrs.obj \
+ $(tktmpdir)\Draw.obj \
+ $(tktmpdir)\Geo.obj \
+ $(tktmpdir)\List.obj \
+# $(tktmpdir)\perfos.obj \
+ $(tktmpdir)\version.obj \
+ $(tktmpdir)\Transfo.obj \
+ $(tktmpdir)\Group.obj \
+ $(tktmpdir)\Icon.obj \
+ $(tktmpdir)\Text.obj \
+ $(tktmpdir)\Color.obj \
+ $(tktmpdir)\Field.obj \
+ $(tktmpdir)\Triangles.obj \
+ $(tktmpdir)\Window.obj \
+ $(tktmpdir)\tkZinc.obj \
+ $(tktmpdir)\OverlapMan.obj \
+ $(tktmpdir)\WinPort.obj \
+ $(tktmpdir)\Image.obj
+
+PTKDLLOBJS = $(ptktmpdir)\Track.obj \
+ $(ptktmpdir)\Tabular.obj \
+ $(ptktmpdir)\Reticle.obj \
+ $(ptktmpdir)\Map.obj \
+ $(ptktmpdir)\Rectangle.obj \
+ $(ptktmpdir)\Arc.obj \
+ $(ptktmpdir)\Curve.obj \
+ $(ptktmpdir)\Item.obj \
+# $(ptktmpdir)\PostScript.obj \
+ $(ptktmpdir)\MapInfo.obj \
+ $(ptktmpdir)\Attrs.obj \
+ $(ptktmpdir)\Draw.obj \
+ $(ptktmpdir)\Geo.obj \
+ $(ptktmpdir)\List.obj \
+# $(ptktmpdir)\perfos.obj \
+ $(ptktmpdir)\version.obj \
+ $(ptktmpdir)\Transfo.obj \
+ $(ptktmpdir)\Group.obj \
+ $(ptktmpdir)\Icon.obj \
+ $(ptktmpdir)\Text.obj \
+ $(ptktmpdir)\Color.obj \
+ $(ptktmpdir)\Field.obj \
+ $(ptktmpdir)\Triangles.obj \
+ $(ptktmpdir)\Window.obj \
+ $(ptktmpdir)\tkZinc.obj \
+ $(ptktmpdir)\OverlapMan.obj \
+ $(ptktmpdir)\WinPort.obj \
+ $(ptktmpdir)\Image.obj
+
+DLL=Tkzinc.dll
+PTKAR=ptkzinc.lib
+
+$(DLL): $(TKDLLOBJS)
+ $(LD) $(DLLLFLAGS) $(TKLIBS) -out:$@ $(TKDLLOBJS)
+
+$(PTKAR): $(PTKDLLOBJS)
+ LIB $(PTKDLLOBJS) /OUT:$@
+
+{$(windir)}.c{$(tktmpdir)}.obj:
+ $(CC) $(TKCPPFLAGS) $(CFLAGS) -Fo$(tktmpdir)\ $<
+
+{$(genericdir)}.c{$(tktmpdir)}.obj:
+ $(CC) $(TKCPPFLAGS) $(CFLAGS) -Fo$(tktmpdir)\ $<
+
+{$(windir)}.c{$(ptktmpdir)}.obj:
+ $(CC) $(PTKCPPFLAGS) $(CFLAGS) -Fo$(ptktmpdir)\ $<
+
+{$(genericdir)}.c{$(ptktmpdir)}.obj:
+ $(CC) $(PTKCPPFLAGS) $(CFLAGS) -Fo$(ptktmpdir)\ $<
+
+mostlyclean:
+ $(RM) *.bak *~ $(tmpdir)\*.obj
+clean:
+ $(RM) *.bak *~ $(tmpdir)\*.obj *.dll