summaryrefslogtreecommitdiff
path: root/app/bin/draw.c
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2016-12-28 16:52:56 +0100
committerJörg Frings-Fürst <debian@jff-webhosting.net>2016-12-28 16:52:56 +0100
commit7b358424ebad9349421acd533c2fa1cbf6cf3e3e (patch)
tree686678532eefed525c242fd214d0cfb2914726c5 /app/bin/draw.c
Initial import of xtrkcad version 1:4.0.2-2
Diffstat (limited to 'app/bin/draw.c')
-rw-r--r--app/bin/draw.c2446
1 files changed, 2446 insertions, 0 deletions
diff --git a/app/bin/draw.c b/app/bin/draw.c
new file mode 100644
index 0000000..1987113
--- /dev/null
+++ b/app/bin/draw.c
@@ -0,0 +1,2446 @@
+/** \file draw.c
+ * Basic drawing functions.
+ *
+ * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/bin/draw.c,v 1.17 2009-12-12 17:20:59 m_fischer Exp $
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef HAVE_MALLOC_C
+#include <malloc.h>
+#endif
+#include <math.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#ifndef WINDOWS
+#include <unistd.h>
+#include <sys/time.h>
+#else
+#include <sys/timeb.h>
+#endif
+
+#include "track.h"
+#include "utility.h"
+#include "misc.h"
+#include "draw.h"
+#include "i18n.h"
+#include "fileio.h"
+
+static void DrawRoomWalls( wBool_t );
+EXPORT void DrawMarkers( void );
+static void ConstraintOrig( coOrd *, coOrd );
+
+static int log_pan = 0;
+static int log_zoom = 0;
+static int log_mouse = 0;
+
+static wFontSize_t drawMaxTextFontSize = 100;
+
+/****************************************************************************
+ *
+ * EXPORTED VARIABLES
+ *
+ */
+
+#define INIT_MAIN_SCALE (8.0)
+#define INIT_MAP_SCALE (64.0)
+#define MAX_MAIN_SCALE (256.0)
+#define MIN_MAIN_SCALE (1.0)
+
+// static char FAR message[STR_LONG_SIZE];
+
+EXPORT wPos_t closePixels = 10;
+EXPORT long maxArcSegStraightLen = 100;
+EXPORT long drawCount;
+EXPORT BOOL_T drawEnable = TRUE;
+EXPORT long currRedraw = 0;
+
+EXPORT wDrawColor drawColorBlack;
+EXPORT wDrawColor drawColorWhite;
+EXPORT wDrawColor drawColorRed;
+EXPORT wDrawColor drawColorBlue;
+EXPORT wDrawColor drawColorGreen;
+EXPORT wDrawColor drawColorAqua;
+EXPORT wDrawColor drawColorPurple;
+EXPORT wDrawColor drawColorGold;
+
+EXPORT DIST_T pixelBins = 80;
+
+/****************************************************************************
+ *
+ * LOCAL VARIABLES
+ *
+ */
+
+static wPos_t infoHeight;
+EXPORT wWin_p mapW;
+EXPORT BOOL_T mapVisible;
+
+EXPORT wDrawColor markerColor;
+EXPORT wDrawColor borderColor;
+EXPORT wDrawColor crossMajorColor;
+EXPORT wDrawColor crossMinorColor;
+EXPORT wDrawColor selectedColor;
+EXPORT wDrawColor normalColor;
+EXPORT wDrawColor elevColorIgnore;
+EXPORT wDrawColor elevColorDefined;
+EXPORT wDrawColor profilePathColor;
+EXPORT wDrawColor exceptionColor;
+
+static wFont_p rulerFp;
+
+static struct {
+ wMessage_p scale_m;
+ wMessage_p count_m;
+ wMessage_p posX_m;
+ wMessage_p posY_m;
+ wMessage_p info_m;
+ wPos_t scale_w;
+ wPos_t count_w;
+ wPos_t pos_w;
+ wPos_t info_w;
+ wBox_p scale_b;
+ wBox_p count_b;
+ wBox_p posX_b;
+ wBox_p posY_b;
+ wBox_p info_b;
+ } infoD;
+
+EXPORT coOrd oldMarker = { 0.0, 0.0 };
+
+EXPORT long dragPixels = 20;
+EXPORT long dragTimeout = 500;
+EXPORT long autoPan = 0;
+EXPORT BOOL_T inError = FALSE;
+
+typedef enum { mouseNone, mouseLeft, mouseRight, mouseLeftPending } mouseState_e;
+static mouseState_e mouseState;
+static int mousePositionx, mousePositiony; /**< position of mouse pointer */
+
+static int delayUpdate = 1;
+
+static char xLabel[] = "X : ";
+static char yLabel[] = "Y : ";
+static char zoomLabel[] = "Zoom : ";
+
+static struct {
+ char * name;
+ double value;
+ wMenuRadio_p pdRadio;
+ wMenuRadio_p btRadio;
+ } zoomList[] = {
+ { "1:10", 1.0 / 10.0 },
+ { "1:5", 1.0 / 5.0 },
+ { "1:2", 1.0 / 2.0 },
+ { "1:1", 1.0 },
+ { "2:1", 2.0 },
+ { "3:1", 3.0 },
+ { "4:1", 4.0 },
+ { "6:1", 6.0 },
+ { "8:1", 8.0 },
+ { "10:1", 10.0 },
+ { "12:1", 12.0 },
+ { "16:1", 16.0 },
+ { "20:1", 20.0 },
+ { "24:1", 24.0 },
+ { "28:1", 28.0 },
+ { "32:1", 32.0 },
+ { "36:1", 36.0 },
+ { "40:1", 40.0 },
+ { "48:1", 48.0 },
+ { "56:1", 56.0 },
+ { "64:1", 64.0 },
+ { "128:1", 128.0 },
+ { "256:1", 256.0 },
+};
+
+
+
+/****************************************************************************
+ *
+ * DRAWING
+ *
+ */
+
+static void MainCoOrd2Pix( drawCmd_p d, coOrd p, wPos_t * x, wPos_t * y )
+{
+ DIST_T t;
+ if (d->angle != 0.0)
+ Rotate( &p, d->orig, -d->angle );
+ p.x = (p.x - d->orig.x) / d->scale;
+ p.y = (p.y - d->orig.y) / d->scale;
+ t = p.x*d->dpi;
+ if ( t > 0.0 )
+ t += 0.5;
+ else
+ t -= 0.5;
+ *x = ((wPos_t)t) + ((d->options&DC_TICKS)?LBORDER:0);
+ t = p.y*d->dpi;
+ if ( t > 0.0 )
+ t += 0.5;
+ else
+ t -= 0.5;
+ *y = ((wPos_t)t) + ((d->options&DC_TICKS)?BBORDER:0);
+}
+
+
+static int Pix2CoOrd_interpolate = 0;
+
+static void MainPix2CoOrd(
+ drawCmd_p d,
+ wPos_t px,
+ wPos_t py,
+ coOrd * posR )
+{
+ DIST_T x, y;
+ DIST_T bins = pixelBins;
+ x = ((((POS_T)((px)-LBORDER))/d->dpi)) * d->scale;
+ y = ((((POS_T)((py)-BBORDER))/d->dpi)) * d->scale;
+ x = (long)(x*bins)/bins;
+ y = (long)(y*bins)/bins;
+if (Pix2CoOrd_interpolate) {
+ DIST_T x1, y1;
+ x1 = ((((POS_T)((px-1)-LBORDER))/d->dpi)) * d->scale;
+ y1 = ((((POS_T)((py-1)-BBORDER))/d->dpi)) * d->scale;
+ x1 = (long)(x1*bins)/bins;
+ y1 = (long)(y1*bins)/bins;
+ if (x == x1) {
+ x += 1/bins/2;
+ printf ("px=%d x1=%0.6f x=%0.6f\n", px, x1, x );
+ }
+ if (y == y1)
+ y += 1/bins/2;
+}
+ x += d->orig.x;
+ y += d->orig.y;
+ posR->x = x;
+ posR->y = y;
+}
+
+
+static void DDrawLine(
+ drawCmd_p d,
+ coOrd p0,
+ coOrd p1,
+ wDrawWidth width,
+ wDrawColor color )
+{
+ wPos_t x0, y0, x1, y1;
+ BOOL_T in0 = FALSE, in1 = FALSE;
+ coOrd orig, size;
+ if (d == &mapD && !mapVisible)
+ return;
+ if ( (d->options&DC_NOCLIP) == 0 ) {
+ if (d->angle == 0.0) {
+ in0 = (p0.x >= d->orig.x && p0.x <= d->orig.x+d->size.x &&
+ p0.y >= d->orig.y && p0.y <= d->orig.y+d->size.y);
+ in1 = (p1.x >= d->orig.x && p1.x <= d->orig.x+d->size.x &&
+ p1.y >= d->orig.y && p1.y <= d->orig.y+d->size.y);
+ }
+ if ( (!in0) || (!in1) ) {
+ orig = d->orig;
+ size = d->size;
+ if (d->options&DC_TICKS) {
+ orig.x -= LBORDER/d->dpi*d->scale;
+ orig.y -= BBORDER/d->dpi*d->scale;
+ size.x += (LBORDER+RBORDER)/d->dpi*d->scale;
+ size.y += (BBORDER+TBORDER)/d->dpi*d->scale;
+ }
+ if (!ClipLine( &p0, &p1, orig, d->angle, size ))
+ return;
+ }
+ }
+ d->CoOrd2Pix(d,p0,&x0,&y0);
+ d->CoOrd2Pix(d,p1,&x1,&y1);
+ drawCount++;
+ if (drawEnable) {
+ wDrawLine( d->d, x0, y0, x1, y1,
+ width, ((d->options&DC_DASH)==0)?wDrawLineSolid:wDrawLineDash,
+ color, (wDrawOpts)d->funcs->options );
+ }
+}
+
+
+static void DDrawArc(
+ drawCmd_p d,
+ coOrd p,
+ DIST_T r,
+ ANGLE_T angle0,
+ ANGLE_T angle1,
+ BOOL_T drawCenter,
+ wDrawWidth width,
+ wDrawColor color )
+{
+ wPos_t x, y;
+ ANGLE_T da;
+ coOrd p0, p1;
+ DIST_T rr;
+ int i, cnt;
+
+ if (d == &mapD && !mapVisible)
+ return;
+ rr = (r / d->scale) * d->dpi + 0.5;
+ if (rr > wDrawGetMaxRadius(d->d)) {
+ da = (maxArcSegStraightLen * 180) / (M_PI * rr);
+ cnt = (int)(angle1/da) + 1;
+ da = angle1 / cnt;
+ PointOnCircle( &p0, p, r, angle0 );
+ for ( i=1; i<=cnt; i++ ) {
+ angle0 += da;
+ PointOnCircle( &p1, p, r, angle0 );
+ DrawLine( d, p0, p1, width, color );
+ p0 = p1;
+ }
+ return;
+ }
+ if (d->angle!=0.0 && angle1 < 360.0)
+ angle0 = NormalizeAngle( angle0-d->angle );
+ d->CoOrd2Pix(d,p,&x,&y);
+ drawCount++;
+ if (drawEnable) {
+ wDrawArc( d->d, x, y, (wPos_t)(rr), angle0, angle1, drawCenter,
+ width, ((d->options&DC_DASH)==0)?wDrawLineSolid:wDrawLineDash,
+ color, (wDrawOpts)d->funcs->options );
+ }
+}
+
+
+static void DDrawString(
+ drawCmd_p d,
+ coOrd p,
+ ANGLE_T a,
+ char * s,
+ wFont_p fp,
+ FONTSIZE_T fontSize,
+ wDrawColor color )
+{
+ wPos_t x, y;
+ if (d == &mapD && !mapVisible)
+ return;
+ fontSize /= d->scale;
+ d->CoOrd2Pix(d,p,&x,&y);
+ wDrawString( d->d, x, y, d->angle-a, s, fp, fontSize, color, (wDrawOpts)d->funcs->options );
+}
+
+
+static void DDrawFillPoly(
+ drawCmd_p d,
+ int cnt,
+ coOrd * pts,
+ wDrawColor color )
+{
+ typedef wPos_t wPos2[2];
+ static dynArr_t wpts_da;
+ int inx;
+ wPos_t x, y;
+ DYNARR_SET( wPos2, wpts_da, cnt * 2 );
+#define wpts(N) DYNARR_N( wPos2, wpts_da, N )
+ for ( inx=0; inx<cnt; inx++ ) {
+ d->CoOrd2Pix( d, pts[inx], &x, &y );
+ wpts(inx)[0] = x;
+ wpts(inx)[1] = y;
+ }
+ wDrawFilledPolygon( d->d, &wpts(0), cnt, color, (wDrawOpts)d->funcs->options );
+}
+
+
+static void DDrawFillCircle(
+ drawCmd_p d,
+ coOrd p,
+ DIST_T r,
+ wDrawColor color )
+{
+ wPos_t x, y;
+ DIST_T rr;
+
+ if (d == &mapD && !mapVisible)
+ return;
+ rr = (r / d->scale) * d->dpi + 0.5;
+ if (rr > wDrawGetMaxRadius(d->d)) {
+#ifdef LATER
+ da = (maxArcSegStraightLen * 180) / (M_PI * rr);
+ cnt = (int)(angle1/da) + 1;
+ da = angle1 / cnt;
+ PointOnCircle( &p0, p, r, angle0 );
+ for ( i=1; i<=cnt; i++ ) {
+ angle0 += da;
+ PointOnCircle( &p1, p, r, angle0 );
+ DrawLine( d, p0, p1, width, color );
+ p0 = p1;
+ }
+#endif
+ return;
+ }
+ d->CoOrd2Pix(d,p,&x,&y);
+ drawCount++;
+ if (drawEnable) {
+ wDrawFilledCircle( d->d, x, y, (wPos_t)(rr),
+ color, (wDrawOpts)d->funcs->options );
+ }
+}
+
+
+EXPORT void DrawHilight( drawCmd_p d, coOrd p, coOrd s )
+{
+ wPos_t x, y, w, h;
+ if (d == &mapD && !mapVisible)
+ return;
+#ifdef LATER
+ if (d->options&DC_TEMPSEGS) {
+ return;
+ }
+ if (d->options&DC_PRINT)
+ return;
+#endif
+ w = (wPos_t)((s.x/d->scale)*d->dpi+0.5);
+ h = (wPos_t)((s.y/d->scale)*d->dpi+0.5);
+ d->CoOrd2Pix(d,p,&x,&y);
+ wDrawFilledRectangle( d->d, x, y, w, h, wDrawColorBlack, wDrawOptTemp );
+}
+
+
+EXPORT void DrawHilightPolygon( drawCmd_p d, coOrd *p, int cnt )
+{
+ wPos_t q[4][2];
+ int i;
+#ifdef LATER
+ if (d->options&DC_TEMPSEGS) {
+ return;
+ }
+ if (d->options&DC_PRINT)
+ return;
+#endif
+ ASSERT( cnt <= 4 );
+ for (i=0; i<cnt; i++) {
+ d->CoOrd2Pix(d,p[i],&q[i][0],&q[i][1]);
+ }
+ wDrawFilledPolygon( d->d, q, cnt, wDrawColorBlack, wDrawOptTemp );
+}
+
+
+EXPORT void DrawMultiString(
+ drawCmd_p d,
+ coOrd pos,
+ char * text,
+ wFont_p fp,
+ wFontSize_t fs,
+ wDrawColor color,
+ ANGLE_T a,
+ coOrd * lo,
+ coOrd * hi)
+{
+ char * cp;
+ POS_T lineH, lineW;
+ coOrd size, textsize;
+ POS_T descent;
+
+ DrawTextSize2( &mainD, "Aqjlp", fp, fs, TRUE, &textsize, &descent );
+ lineH = textsize.y+descent;
+ size.x = 0.0;
+ size.y = 0.0;
+ while (1) {
+ cp = message;
+ while (*text != '\0' && *text != '\n')
+ *cp++ = *text++;
+ *cp = '\0';
+ DrawTextSize2( &mainD, message, fp, fs, TRUE, &textsize, &descent );
+ lineW = textsize.x;
+ if (lineW>size.x)
+ size.x = lineW;
+ DrawString( d, pos, 0.0, message, fp, fs, color );
+ pos.y -= lineH;
+ size.y += lineH;
+ if (*text)
+ break;
+ text++;
+ }
+ *lo = pos;
+ hi->x = pos.x;
+ hi->y = pos.y+size.y;
+}
+
+
+EXPORT void DrawBoxedString(
+ int style,
+ drawCmd_p d,
+ coOrd pos,
+ char * text,
+ wFont_p fp, wFontSize_t fs,
+ wDrawColor color,
+ ANGLE_T a )
+{
+ coOrd size, p[4], p0=pos, p1, p2;
+ static int bw=5, bh=4, br=2, bb=2;
+ static double arrowScale = 0.5;
+ long options = d->options;
+ POS_T descent;
+ /*DrawMultiString( d, pos, text, fp, fs, color, a, &lo, &hi );*/
+ if ( fs < 2*d->scale )
+ return;
+#ifndef WINDOWS
+ if ( ( d->options & DC_PRINT) != 0 ) {
+ double scale = ((FLOAT_T)fs)/((FLOAT_T)drawMaxTextFontSize)/72.0;
+ wPos_t w, h, d;
+ wDrawGetTextSize( &w, &h, &d, mainD.d, text, fp, drawMaxTextFontSize );
+ size.x = w*scale;
+ size.y = h*scale;
+ descent = d*scale;
+ } else
+#endif
+ DrawTextSize2( &mainD, text, fp, fs, TRUE, &size, &descent );
+#ifdef WINDOWS
+ /*h -= 15;*/
+#endif
+ p0.x -= size.x/2.0;
+ p0.y -= size.y/2.0;
+ if (style == BOX_NONE || d == &mapD) {
+ DrawString( d, p0, 0.0, text, fp, fs, color );
+ return;
+ }
+ size.x += bw*d->scale/d->dpi;
+ size.y += bh*d->scale/d->dpi;
+ size.y += descent;
+ p[0] = p0;
+ p[0].x -= br*d->scale/d->dpi;
+ p[0].y -= bb*d->scale/d->dpi+descent;
+ p[1].y = p[0].y;
+ p[2].y = p[3].y = p[0].y + size.y;
+ p[1].x = p[2].x = p[0].x + size.x;
+ p[3].x = p[0].x;
+ d->options &= ~DC_DASH;
+ switch (style) {
+ case BOX_ARROW:
+ Translate( &p1, pos, a, size.x+size.y );
+ ClipLine( &pos, &p1, p[0], 0.0, size );
+ Translate( &p2, p1, a, size.y*arrowScale );
+ DrawLine( d, p1, p2, 0, color );
+ Translate( &p1, p2, a+150, size.y*0.7*arrowScale );
+ DrawLine( d, p1, p2, 0, color );
+ Translate( &p1, p2, a-150, size.y*0.7*arrowScale );
+ DrawLine( d, p1, p2, 0, color );
+ case BOX_BOX:
+ DrawLine( d, p[1], p[2], 0, color );
+ DrawLine( d, p[2], p[3], 0, color );
+ DrawLine( d, p[3], p[0], 0, color );
+ case BOX_UNDERLINE:
+ DrawLine( d, p[0], p[1], 0, color );
+ DrawString( d, p0, 0.0, text, fp, fs, color );
+ break;
+ case BOX_INVERT:
+ DrawFillPoly( d, 4, p, color );
+ if ( color != wDrawColorWhite )
+ DrawString( d, p0, 0.0, text, fp, fs, wDrawColorWhite );
+ break;
+ case BOX_BACKGROUND:
+ DrawFillPoly( d, 4, p, wDrawColorWhite );
+ DrawString( d, p0, 0.0, text, fp, fs, color );
+ break;
+ }
+ d->options = options;
+}
+
+
+EXPORT void DrawTextSize2(
+ drawCmd_p dp,
+ char * text,
+ wFont_p fp,
+ wFontSize_t fs,
+ BOOL_T relative,
+ coOrd * size,
+ POS_T * descent )
+{
+ wPos_t w, h, d;
+ FLOAT_T scale = 1.0;
+ if ( relative )
+ fs /= dp->scale;
+ if ( fs > drawMaxTextFontSize ) {
+ scale = ((FLOAT_T)fs)/((FLOAT_T)drawMaxTextFontSize);
+ fs = drawMaxTextFontSize;
+ }
+ wDrawGetTextSize( &w, &h, &d, dp->d, text, fp, fs );
+ size->x = SCALEX(mainD,w)*scale;
+ size->y = SCALEY(mainD,h)*scale;
+ *descent = SCALEY(mainD,d)*scale;
+ if ( relative ) {
+ size->x *= dp->scale;
+ size->y *= dp->scale;
+ *descent *= dp->scale;
+ }
+/* printf( "DTS2(\"%s\",%0.3f,%d) = (w%d,h%d,d%d) *%0.3f x%0.3f y%0.3f %0.3f\n", text, fs, relative, w, h, d, scale, size->x, size->y, *descent );*/
+}
+
+EXPORT void DrawTextSize(
+ drawCmd_p dp,
+ char * text,
+ wFont_p fp,
+ wFontSize_t fs,
+ BOOL_T relative,
+ coOrd * size )
+{
+ POS_T descent;
+ DrawTextSize2( dp, text, fp, fs, relative, size, &descent );
+}
+
+
+static void DDrawBitMap( drawCmd_p d, coOrd p, wDrawBitMap_p bm, wDrawColor color)
+{
+ wPos_t x, y;
+#ifdef LATER
+ if (d->options&DC_TEMPSEGS) {
+ return;
+ }
+ if (d->options&DC_PRINT)
+ return;
+#endif
+ d->CoOrd2Pix( d, p, &x, &y );
+ wDrawBitMap( d->d, bm, x, y, color, (wDrawOpts)d->funcs->options );
+}
+
+
+static void TempSegLine(
+ drawCmd_p d,
+ coOrd p0,
+ coOrd p1,
+ wDrawWidth width,
+ wDrawColor color )
+{
+ DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 );
+ tempSegs(tempSegs_da.cnt-1).type = SEG_STRLIN;
+ tempSegs(tempSegs_da.cnt-1).color = color;
+ if (d->options&DC_SIMPLE)
+ tempSegs(tempSegs_da.cnt-1).width = 0;
+ else
+ tempSegs(tempSegs_da.cnt-1).width = width*d->scale/d->dpi;
+ tempSegs(tempSegs_da.cnt-1).u.l.pos[0] = p0;
+ tempSegs(tempSegs_da.cnt-1).u.l.pos[1] = p1;
+}
+
+
+static void TempSegArc(
+ drawCmd_p d,
+ coOrd p,
+ DIST_T r,
+ ANGLE_T angle0,
+ ANGLE_T angle1,
+ BOOL_T drawCenter,
+ wDrawWidth width,
+ wDrawColor color )
+{
+ DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 );
+ tempSegs(tempSegs_da.cnt-1).type = SEG_CRVLIN;
+ tempSegs(tempSegs_da.cnt-1).color = color;
+ if (d->options&DC_SIMPLE)
+ tempSegs(tempSegs_da.cnt-1).width = 0;
+ else
+ tempSegs(tempSegs_da.cnt-1).width = width*d->scale/d->dpi;
+ tempSegs(tempSegs_da.cnt-1).u.c.center = p;
+ tempSegs(tempSegs_da.cnt-1).u.c.radius = r;
+ tempSegs(tempSegs_da.cnt-1).u.c.a0 = angle0;
+ tempSegs(tempSegs_da.cnt-1).u.c.a1 = angle1;
+}
+
+
+static void TempSegString(
+ drawCmd_p d,
+ coOrd p,
+ ANGLE_T a,
+ char * s,
+ wFont_p fp,
+ FONTSIZE_T fontSize,
+ wDrawColor color )
+{
+ DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 );
+ tempSegs(tempSegs_da.cnt-1).type = SEG_TEXT;
+ tempSegs(tempSegs_da.cnt-1).color = color;
+ tempSegs(tempSegs_da.cnt-1).width = 0;
+ tempSegs(tempSegs_da.cnt-1).u.t.pos = p;
+ tempSegs(tempSegs_da.cnt-1).u.t.angle = a;
+ tempSegs(tempSegs_da.cnt-1).u.t.fontP = fp;
+ tempSegs(tempSegs_da.cnt-1).u.t.fontSize = fontSize;
+ tempSegs(tempSegs_da.cnt-1).u.t.string = s;
+}
+
+
+static void TempSegFillPoly(
+ drawCmd_p d,
+ int cnt,
+ coOrd * pts,
+ wDrawColor color )
+{
+#ifdef LATER
+ pts is not guaranteed to valid
+ DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 );
+ tempSegs(tempSegs_da.cnt-1).type = SEG_FILPOLY;
+ tempSegs(tempSegs_da.cnt-1).color = color;
+ tempSegs(tempSegs_da.cnt-1).width = 0;
+ tempSegs(tempSegs_da.cnt-1).u.p.cnt = cnt;
+ tempSegs(tempSegs_da.cnt-1).u.p.pts = pts;
+#endif
+ return;
+}
+
+
+static void TempSegFillCircle(
+ drawCmd_p d,
+ coOrd p,
+ DIST_T r,
+ wDrawColor color )
+{
+ DYNARR_APPEND( trkSeg_t, tempSegs_da, 10 );
+ tempSegs(tempSegs_da.cnt-1).type = SEG_FILCRCL;
+ tempSegs(tempSegs_da.cnt-1).color = color;
+ tempSegs(tempSegs_da.cnt-1).width = 0;
+ tempSegs(tempSegs_da.cnt-1).u.c.center = p;
+ tempSegs(tempSegs_da.cnt-1).u.c.radius = r;
+ tempSegs(tempSegs_da.cnt-1).u.c.a0 = 0.0;
+ tempSegs(tempSegs_da.cnt-1).u.c.a1 = 360.0;
+}
+
+
+static void NoDrawBitMap( drawCmd_p d, coOrd p, wDrawBitMap_p bm, wDrawColor color )
+{
+}
+
+
+
+EXPORT drawFuncs_t screenDrawFuncs = {
+ 0,
+ DDrawLine,
+ DDrawArc,
+ DDrawString,
+ DDrawBitMap,
+ DDrawFillPoly,
+ DDrawFillCircle };
+
+EXPORT drawFuncs_t tempDrawFuncs = {
+ wDrawOptTemp,
+ DDrawLine,
+ DDrawArc,
+ DDrawString,
+ DDrawBitMap,
+ DDrawFillPoly,
+ DDrawFillCircle };
+
+EXPORT drawFuncs_t printDrawFuncs = {
+ 0,
+ DDrawLine,
+ DDrawArc,
+ DDrawString,
+ NoDrawBitMap,
+ DDrawFillPoly,
+ DDrawFillCircle };
+
+EXPORT drawFuncs_t tempSegDrawFuncs = {
+ 0,
+ TempSegLine,
+ TempSegArc,
+ TempSegString,
+ NoDrawBitMap,
+ TempSegFillPoly,
+ TempSegFillCircle };
+
+EXPORT drawCmd_t mainD = {
+ NULL, &screenDrawFuncs, DC_TICKS, INIT_MAIN_SCALE, 0.0, {0.0,0.0}, {0.0,0.0}, MainPix2CoOrd, MainCoOrd2Pix };
+
+EXPORT drawCmd_t tempD = {
+ NULL, &tempDrawFuncs, DC_TICKS|DC_SIMPLE, INIT_MAIN_SCALE, 0.0, {0.0,0.0}, {0.0,0.0}, MainPix2CoOrd, MainCoOrd2Pix };
+
+EXPORT drawCmd_t mapD = {
+ NULL, &screenDrawFuncs, 0, INIT_MAP_SCALE, 0.0, {0.0,0.0}, {96.0,48.0}, Pix2CoOrd, CoOrd2Pix };
+
+
+/*****************************************************************************
+ *
+ * MAIN AND MAP WINDOW DEFINTIONS
+ *
+ */
+
+
+static wPos_t info_yb_offset = 2;
+static wPos_t info_ym_offset = 3;
+static wPos_t six = 2;
+static wPos_t info_xm_offset = 2;
+#define NUM_INFOCTL (4)
+static wControl_p curInfoControl[NUM_INFOCTL];
+static wPos_t curInfoLabelWidth[NUM_INFOCTL];
+
+/**
+ * Determine the width of a mouse pointer position string ( coordinate plus label ).
+ *
+ * \return width of position string
+ */
+static wPos_t GetInfoPosWidth( void )
+{
+ wPos_t labelWidth;
+
+ DIST_T dist;
+ if ( mapD.size.x > mapD.size.y )
+ dist = mapD.size.x;
+ else
+ dist = mapD.size.y;
+ if ( units == UNITS_METRIC ) {
+ dist *= 2.54;
+ if ( dist >= 1000 )
+ dist = 9999.999*2.54;
+ else if ( dist >= 100 )
+ dist = 999.999*2.54;
+ else if ( dist >= 10 )
+ dist = 99.999*2.54;
+ } else {
+ if ( dist >= 100*12 )
+ dist = 999.0*12.0+11.0+3.0/4.0-1.0/64.0;
+ else if ( dist >= 10*12 )
+ dist = 99.0*12.0+11.0+3.0/4.0-1.0/64.0;
+ else if ( dist >= 1*12 )
+ dist = 9.0*12.0+11.0+3.0/4.0-1.0/64.0;
+ }
+
+ labelWidth = (wLabelWidth( xLabel ) > wLabelWidth( yLabel ) ? wLabelWidth( xLabel ):wLabelWidth( yLabel ));
+
+ return wLabelWidth( FormatDistance(dist) ) + labelWidth;
+}
+
+/**
+ * Initialize the status line at the bottom of the window.
+ *
+ */
+
+EXPORT void InitInfoBar( void )
+{
+ wPos_t width, height, y, yb, ym, x, boxH;
+ wWinGetSize( mainW, &width, &height );
+ infoHeight = 3 + wMessageGetHeight( 0L ) + 3;
+ y = height - infoHeight;
+ y -= 19; /* Kludge for MSW */
+ infoD.pos_w = GetInfoPosWidth() + 2;
+ infoD.scale_w = wLabelWidth( "999:1" ) + wLabelWidth( zoomLabel ) + 6;
+ /* we do not use the count label for the moment */
+ infoD.count_w = 0;
+ infoD.info_w = width - infoD.pos_w*2 - infoD.scale_w - infoD.count_w - 45;
+ if (infoD.info_w <= 0) {
+ infoD.info_w = 10;
+ }
+ yb = y+info_yb_offset;
+ ym = y+info_ym_offset;
+ boxH = infoHeight-5;
+ x = 0;
+ infoD.scale_b = wBoxCreate( mainW, x, yb, NULL, wBoxBelow, infoD.scale_w, boxH );
+ infoD.scale_m = wMessageCreate( mainW, x+info_xm_offset, ym, "infoBarScale", infoD.scale_w-six, zoomLabel );
+ x += infoD.scale_w + 10;
+ infoD.posX_b = wBoxCreate( mainW, x, yb, NULL, wBoxBelow, infoD.pos_w, boxH );
+ infoD.posX_m = wMessageCreate( mainW, x+info_xm_offset, ym, "infoBarPosX", infoD.pos_w-six, xLabel );
+ x += infoD.pos_w + 5;
+ infoD.posY_b = wBoxCreate( mainW, x, yb, NULL, wBoxBelow, infoD.pos_w, boxH );
+ infoD.posY_m = wMessageCreate( mainW, x+info_xm_offset, ym, "infoBarPosY", infoD.pos_w-six, yLabel );
+ x += infoD.pos_w + 10;
+ infoD.info_b = wBoxCreate( mainW, x, yb, NULL, wBoxBelow, infoD.info_w, boxH );
+ infoD.info_m = wMessageCreate( mainW, x+info_xm_offset, ym, "infoBarStatus", infoD.info_w-six, "" );
+}
+
+
+static void SetInfoBar( void )
+{
+ wPos_t width, height, y, yb, ym, x, boxH;
+ int inx;
+ static long oldDistanceFormat = -1;
+ long newDistanceFormat;
+ wWinGetSize( mainW, &width, &height );
+ y = height - infoHeight;
+ newDistanceFormat = GetDistanceFormat();
+ if ( newDistanceFormat != oldDistanceFormat ) {
+ infoD.pos_w = GetInfoPosWidth() + 2;
+ wBoxSetSize( infoD.posX_b, infoD.pos_w, infoHeight-5 );
+ wMessageSetWidth( infoD.posX_m, infoD.pos_w-six );
+ wBoxSetSize( infoD.posY_b, infoD.pos_w, infoHeight-5 );
+ wMessageSetWidth( infoD.posY_m, infoD.pos_w-six );
+ }
+ infoD.info_w = width - infoD.pos_w*2 - infoD.scale_w - infoD.count_w - 40 + 4;
+ if (infoD.info_w <= 0) {
+ infoD.info_w = 10;
+ }
+ yb = y+info_yb_offset;
+ ym = y+info_ym_offset;
+ boxH = infoHeight-5;
+ wWinClear( mainW, 0, y, width, infoHeight );
+ x = 0;
+ wControlSetPos( (wControl_p)infoD.scale_b, x, yb );
+ wControlSetPos( (wControl_p)infoD.scale_m, x+info_xm_offset, ym );
+ x += infoD.scale_w + 10;
+ wControlSetPos( (wControl_p)infoD.posX_b, x, yb );
+ wControlSetPos( (wControl_p)infoD.posX_m, x+info_xm_offset, ym );
+ x += infoD.pos_w + 5;
+ wControlSetPos( (wControl_p)infoD.posY_b, x, yb );
+ wControlSetPos( (wControl_p)infoD.posY_m, x+info_xm_offset, ym );
+ x += infoD.pos_w + 10;
+ wControlSetPos( (wControl_p)infoD.info_b, x, yb );
+ wControlSetPos( (wControl_p)infoD.info_m, x+info_xm_offset, ym );
+ wBoxSetSize( infoD.info_b, infoD.info_w, boxH );
+ wMessageSetWidth( infoD.info_m, infoD.info_w-six );
+ if (curInfoControl[0]) {
+ x = wControlGetPosX( (wControl_p)infoD.info_m );
+#ifndef WINDOWS
+ yb -= 2;
+#endif
+ for ( inx=0; curInfoControl[inx]; inx++ ) {
+ x += curInfoLabelWidth[inx];
+ wControlSetPos( curInfoControl[inx], x, yb );
+ x += wControlGetWidth( curInfoControl[inx] )+3;
+ wControlShow( curInfoControl[inx], TRUE );
+ }
+ }
+}
+
+
+static void InfoScale( void )
+{
+ if (mainD.scale >= 1)
+ sprintf( message, "%s%0.0f:1", zoomLabel, mainD.scale );
+ else
+ sprintf( message, "%s1:%0.0f", zoomLabel, floor(1/mainD.scale+0.5) );
+ wMessageSetValue( infoD.scale_m, message );
+}
+
+EXPORT void InfoCount( wIndex_t count )
+{
+/*
+ sprintf( message, "%d", count );
+ wMessageSetValue( infoD.count_m, message );
+*/
+}
+
+EXPORT void InfoPos( coOrd pos )
+{
+#ifdef LATER
+ wPos_t ww, hh;
+ DIST_T w, h;
+#endif
+ wPos_t x, y;
+
+ sprintf( message, "%s%s", xLabel, FormatDistance(pos.x) );
+ wMessageSetValue( infoD.posX_m, message );
+ sprintf( message, "%s%s", yLabel, FormatDistance(pos.y) );
+ wMessageSetValue( infoD.posY_m, message );
+#ifdef LATER
+ wDrawGetSize( mainD.d, &ww, &hh );
+ w = (DIST_T)(ww/mainD.dpi);
+ h = (DIST_T)(hh/mainD.dpi);
+ /*wDrawClip( mainD.d, 0, 0, w, h );*/
+#endif
+ mainD.CoOrd2Pix(&mainD,oldMarker,&x,&y);
+ wDrawLine( mainD.d, 0, y, (wPos_t)(LBORDER), y,
+ 0, wDrawLineSolid, markerColor, wDrawOptTemp );
+ wDrawLine( mainD.d, x, 0, x, (wPos_t)(BBORDER),
+ 0, wDrawLineSolid, markerColor, wDrawOptTemp );
+
+ mainD.CoOrd2Pix(&mainD,pos,&x,&y);
+ wDrawLine( mainD.d, 0, y, (wPos_t)(LBORDER), y,
+ 0, wDrawLineSolid, markerColor, wDrawOptTemp );
+ wDrawLine( mainD.d, x, 0, x, (wPos_t)(BBORDER),
+ 0, wDrawLineSolid, markerColor, wDrawOptTemp );
+#ifdef LATER
+ /*wDrawClip( mainD.d, LBORDER, BBORDER,
+ w-(LBORDER+RBORDER), h-(BBORDER+TBORDER) );*/
+#endif
+ oldMarker = pos;
+}
+
+static wControl_p deferSubstituteControls[NUM_INFOCTL+1];
+static char * deferSubstituteLabels[NUM_INFOCTL];
+
+EXPORT void InfoSubstituteControls(
+ wControl_p * controls,
+ char ** labels )
+{
+ wPos_t x, y;
+ int inx;
+ for ( inx=0; inx<NUM_INFOCTL; inx++ ) {
+ if (curInfoControl[inx]) {
+ wControlShow( curInfoControl[inx], FALSE );
+ curInfoControl[inx] = NULL;
+ }
+ curInfoLabelWidth[inx] = 0;
+ curInfoControl[inx] = NULL;
+ }
+ if ( inError && ( controls!=NULL && controls[0]!=NULL) ) {
+ memcpy( deferSubstituteControls, controls, sizeof deferSubstituteControls );
+ memcpy( deferSubstituteLabels, labels, sizeof deferSubstituteLabels );
+ }
+ if ( inError || controls == NULL || controls[0]==NULL ) {
+ wControlShow( (wControl_p)infoD.info_m, TRUE );
+ return;
+ }
+ x = wControlGetPosX( (wControl_p)infoD.info_m );
+ y = wControlGetPosY( (wControl_p)infoD.info_m );
+#ifndef WINDOWS
+ y -= 3;
+#endif
+ wMessageSetValue( infoD.info_m, "" );
+ wControlShow( (wControl_p)infoD.info_m, FALSE );
+ for ( inx=0; controls[inx]; inx++ ) {
+ curInfoLabelWidth[inx] = wLabelWidth(_(labels[inx]));
+ x += curInfoLabelWidth[inx];
+ wControlSetPos( controls[inx], x, y );
+ x += wControlGetWidth( controls[inx] );
+ wControlSetLabel( controls[inx], _(labels[inx]) );
+ wControlShow( controls[inx], TRUE );
+ curInfoControl[inx] = controls[inx];
+ x += 3;
+ }
+ curInfoControl[inx] = NULL;
+ deferSubstituteControls[0] = NULL;
+}
+
+
+#ifdef LATER
+EXPORT void InfoSubstituteControl(
+ wControl_p control1,
+ char * label1,
+ wControl_p control2,
+ char * label2 )
+{
+ wControl_p controls[3];
+ wPos_t widths[2];
+
+ if (control1 == NULL) {
+ InfoSubstituteControls( NULL, NULL );
+ } else {
+ controls[0] = control1;
+ controls[1] = control2;
+ controls[2] = NULL;
+ widths[0] = wLabelWidth( label1 );
+ if (label2)
+ widths[1] = wLabelWidth( label2 );
+ else
+ widths[1] = 0;
+ InfoSubstituteControls( controls, widths );
+#ifdef LATER
+ if (curInfoControl[0]) {
+ wControlShow( curInfoControl[0], FALSE );
+ curInfoControl[0] = NULL;
+ }
+ if (curInfoControl[1]) {
+ wControlShow( curInfoControl[1], FALSE );
+ curInfoControl[1] = NULL;
+ }
+ wControlShow( (wControl_p)infoD.info_m, TRUE );
+ } else {
+ if (curInfoControl[0])
+ wControlShow( curInfoControl[0], FALSE );
+ if (curInfoControl[1])
+ wControlShow( curInfoControl[1], FALSE );
+ x = wControlGetPosX( (wControl_p)infoD.info_m );
+ y = wControlGetPosY( (wControl_p)infoD.info_m );
+ curInfoLabelWidth[0] = wLabelWidth( label1 );
+ x += curInfoLabelWidth[0];
+ wControlShow( (wControl_p)infoD.info_m, FALSE );
+ wControlSetPos( control1, x, y );
+ wControlShow( control1, TRUE );
+ curInfoControl[0] = control1;
+ curInfoControl[1] = NULL;
+ if (control2 != NULL) {
+ curInfoLabelWidth[1] = wLabelWidth( label2 );
+ x = wControlBeside( curInfoControl[0] ) + 10;
+ x += curInfoLabelWidth[1]+10;
+ wControlSetPos( control2, x, y );
+ wControlShow( control2, TRUE );
+ curInfoControl[1] = control2;
+ }
+#endif
+ }
+}
+#endif
+
+
+EXPORT void SetMessage( char * msg )
+{
+ wMessageSetValue( infoD.info_m, msg );
+}
+
+
+static void ChangeMapScale( void )
+{
+ wPos_t w, h;
+ wPos_t dw, dh;
+ FLOAT_T fw, fh;
+
+ wGetDisplaySize( &dw, &dh );
+ dw /= 2;
+ dh /= 2;
+ fw = ((mapD.size.x/mapD.scale)*mapD.dpi + 0.5)+2;
+ fh = ((mapD.size.y/mapD.scale)*mapD.dpi + 0.5)+2;
+ if (fw > dw || fh > dh) {
+ if (fw/dw > fh/dh) {
+ mapD.scale = ceil(mapD.size.x*mapD.dpi/dw);
+ } else {
+ mapD.scale = ceil(mapD.size.y*mapD.dpi/dh);
+ }
+ mapScale = (long)mapD.scale;
+ fw = ((mapD.size.x/mapD.scale)*mapD.dpi + 0.5)+2;
+ fh = ((mapD.size.y/mapD.scale)*mapD.dpi + 0.5)+2;
+ } else if ( fw < 100.0 && fh < 100.0 ) {
+ if (fw > fh) {
+ mapD.scale = ceil(mapD.size.x*mapD.dpi/100);
+ } else {
+ mapD.scale = ceil(mapD.size.y*mapD.dpi/100);
+ }
+ mapScale = (long)mapD.scale;
+ fw = ((mapD.size.x/mapD.scale)*mapD.dpi + 0.5)+2;
+ fh = ((mapD.size.y/mapD.scale)*mapD.dpi + 0.5)+2;
+ }
+ w = (wPos_t)fw;
+ h = (wPos_t)fh;
+ wWinSetSize( mapW, w+DlgSepLeft+DlgSepRight, h+DlgSepTop+DlgSepBottom );
+ wDrawSetSize( mapD.d, w, h );
+}
+
+
+EXPORT BOOL_T SetRoomSize( coOrd size )
+{
+ if (size.x < 12.0)
+ size.x = 12.0;
+ if (size.y < 12.0)
+ size.y = 12.0;
+ if ( mapD.size.x == size.x &&
+ mapD.size.y == size.y )
+ return TRUE;
+ mapD.size = size;
+ if ( mapW == NULL)
+ return TRUE;
+ ChangeMapScale();
+ ConstraintOrig( &mainD.orig, mainD.size );
+ tempD.orig = mainD.orig;
+ /*MainRedraw();*/
+ wPrefSetFloat( "draw", "roomsizeX", mapD.size.x );
+ wPrefSetFloat( "draw", "roomsizeY", mapD.size.y );
+ return TRUE;
+}
+
+
+EXPORT void GetRoomSize( coOrd * froomSize )
+{
+ *froomSize = mapD.size;
+}
+
+
+static void MapRedraw( void )
+{
+ if (inPlaybackQuit)
+ return;
+#ifdef VERBOSE
+lprintf("MapRedraw\n");
+#endif
+ if (!mapVisible)
+ return;
+
+ if (delayUpdate)
+ wDrawDelayUpdate( mapD.d, TRUE );
+ wSetCursor( wCursorWait );
+ wDrawClear( mapD.d );
+ DrawTracks( &mapD, mapD.scale, mapD.orig, mapD.size );
+ DrawMapBoundingBox( TRUE );
+ wSetCursor( wCursorNormal );
+ wDrawDelayUpdate( mapD.d, FALSE );
+}
+
+
+static void MapResize( void )
+{
+ mapD.scale = mapScale;
+ ChangeMapScale();
+ MapRedraw();
+}
+
+
+#ifdef LATER
+static void MapProc( wWin_p win, winProcEvent e, void * data )
+{
+ switch( e ) {
+ case wResize_e:
+ if (mapD.d == NULL)
+ return;
+ DrawMapBoundingBox( FALSE );
+ ChangeMapScale();
+ break;
+ case wClose_e:
+ mapVisible = FALSE;
+ break;
+ /*case wRedraw_e:
+ if (mapD.d == NULL)
+ break;
+ MapRedraw();
+ break;*/
+ default:
+ break;
+ }
+}
+#endif
+
+
+EXPORT void SetMainSize( void )
+{
+ wPos_t ww, hh;
+ DIST_T w, h;
+ wDrawGetSize( mainD.d, &ww, &hh );
+ ww -= LBORDER+RBORDER;
+ hh -= BBORDER+TBORDER;
+ w = ww/mainD.dpi;
+ h = hh/mainD.dpi;
+ mainD.size.x = w * mainD.scale;
+ mainD.size.y = h * mainD.scale;
+ tempD.size = mainD.size;
+}
+
+
+EXPORT void MainRedraw( void )
+{
+#ifdef LATER
+ wPos_t ww, hh;
+ DIST_T w, h;
+#endif
+
+ coOrd orig, size;
+ DIST_T t1;
+ if (inPlaybackQuit)
+ return;
+#ifdef VERBOSE
+lprintf("mainRedraw\n");
+#endif
+
+ wSetCursor( wCursorWait );
+ if (delayUpdate)
+ wDrawDelayUpdate( mainD.d, TRUE );
+#ifdef LATER
+ wDrawGetSize( mainD.d, &ww, &hh );
+ w = ww/mainD.dpi;
+ h = hh/mainD.dpi;
+#endif
+ SetMainSize();
+#ifdef LATER
+ /*wDrawClip( mainD.d, 0, 0, w, h );*/
+#endif
+ t1 = mainD.dpi/mainD.scale;
+ if (units == UNITS_ENGLISH) {
+ t1 /= 2.0;
+ for ( pixelBins=0.25; pixelBins<t1; pixelBins*=2.0 );
+ } else {
+ pixelBins = 50.8;
+ if (pixelBins >= t1)
+ while (1) {
+ if ( pixelBins <= t1 )
+ break;
+ pixelBins /= 2.0;
+ if ( pixelBins <= t1 )
+ break;
+ pixelBins /= 2.5;
+ if ( pixelBins <= t1 )
+ break;
+ pixelBins /= 2.0;
+ }
+ }
+ ConstraintOrig( &mainD.orig, mainD.size );
+ tempD.orig = mainD.orig;
+ wDrawClear( mainD.d );
+ currRedraw++;
+ DrawSnapGrid( &tempD, mapD.size, TRUE );
+ DrawRoomWalls( TRUE );
+ orig = mainD.orig;
+ size = mainD.size;
+ orig.x -= RBORDER/mainD.dpi*mainD.scale;
+ orig.y -= BBORDER/mainD.dpi*mainD.scale;
+ size.x += (RBORDER+LBORDER)/mainD.dpi*mainD.scale;
+ size.y += (BBORDER+TBORDER)/mainD.dpi*mainD.scale;
+ DrawTracks( &mainD, mainD.scale, orig, size );
+ RulerRedraw( FALSE );
+ DoCurCommand( C_REDRAW, zero );
+ DrawMarkers();
+ wSetCursor( wCursorNormal );
+ InfoScale();
+ wDrawDelayUpdate( mainD.d, FALSE );
+}
+
+
+EXPORT void MainProc( wWin_p win, winProcEvent e, void * data )
+{
+ wPos_t width, height;
+ switch( e ) {
+ case wResize_e:
+ if (mainD.d == NULL)
+ return;
+ DrawMapBoundingBox( FALSE );
+ wWinGetSize( mainW, &width, &height );
+ LayoutToolBar();
+ height -= (toolbarHeight+infoHeight);
+ if (height >= 0) {
+ wDrawSetSize( mainD.d, width, height );
+ wControlSetPos( (wControl_p)mainD.d, 0, toolbarHeight );
+ SetMainSize();
+ ConstraintOrig( &mainD.orig, mainD.size );
+ tempD.orig = mainD.orig;
+ SetInfoBar();
+ MainRedraw();
+ wPrefSetInteger( "draw", "mainwidth", width );
+ wPrefSetInteger( "draw", "mainheight", height );
+ }
+ DrawMapBoundingBox( TRUE );
+ break;
+ case wQuit_e:
+ if (changed &&
+ NoticeMessage( MSG_SAVE_CHANGES, _("Save"), _("Quit")))
+ DoSave(NULL);
+
+ CleanupFiles();
+ SaveState();
+ CleanupCustom();
+ break;
+ case wClose_e:
+ /* shutdown the application */
+ DoQuit();
+ break;
+ default:
+ break;
+ }
+}
+
+
+#ifdef WINDOWS
+int profRedraw = 0;
+void
+#ifndef WIN32
+_far _pascal
+#endif
+ProfStart( void );
+void
+#ifndef WIN32
+_far _pascal
+#endif
+ProfStop( void );
+#endif
+
+EXPORT void DoRedraw( void )
+{
+#ifdef WINDOWS
+#ifndef WIN32
+ if (profRedraw)
+ ProfStart();
+#endif
+#endif
+ MapRedraw();
+ MainRedraw();
+#ifdef WINDOWS
+#ifndef WIN32
+ if (profRedraw)
+ ProfStop();
+#endif
+#endif
+
+
+}
+
+/*****************************************************************************
+ *
+ * RULERS and OTHER DECORATIONS
+ *
+ */
+
+
+static void DrawRoomWalls( wBool_t t )
+{
+ coOrd p01, p11, p10;
+
+ if (mainD.d == NULL)
+ return;
+#ifdef LATER
+ wDrawGetDim( mainD.d, &w, &h );
+#endif
+ DrawTicks( &mainD, mapD.size );
+
+ p01.x = p10.y = 0.0;
+ p11.x = p10.x = mapD.size.x;
+ p01.y = p11.y = mapD.size.y;
+ DrawLine( &mainD, p01, p11, 3, t?borderColor:wDrawColorWhite );
+ DrawLine( &mainD, p11, p10, 3, t?borderColor:wDrawColorWhite );
+#ifdef LATER
+ /*wDrawClip( mainD.d, LBORDER, BBORDER,
+ w-(LBORDER+RBORDER), h-(BBORDER+TBORDER) );*/
+#endif
+}
+
+
+EXPORT void DrawMarkers( void )
+{
+ wPos_t x, y;
+ mainD.CoOrd2Pix(&mainD,oldMarker,&x,&y);
+ wDrawLine( mainD.d, 0, y, (wPos_t)LBORDER, y,
+ 0, wDrawLineSolid, markerColor, wDrawOptTemp );
+ wDrawLine( mainD.d, x, 0, x, (wPos_t)BBORDER,
+ 0, wDrawLineSolid, markerColor, wDrawOptTemp );
+}
+
+static DIST_T rulerFontSize = 12.0;
+
+
+EXPORT void DrawRuler(
+ drawCmd_p d,
+ coOrd pos0,
+ coOrd pos1,
+ DIST_T offset,
+ int number,
+ int tickSide,
+ wDrawColor color )
+{
+ coOrd orig = pos0;
+ wAngle_t a, aa;
+ DIST_T start, end;
+ long inch, lastInch;
+ wPos_t len;
+ int digit;
+ char quote;
+ char message[10];
+ coOrd d_orig, d_size;
+ wFontSize_t fs;
+ long mm, mm0, mm1, power;
+ wPos_t x0, y0, x1, y1;
+ long dxn, dyn;
+ static int lengths[8] = {
+ 0, 2, 4, 2, 6, 2, 4, 2 };
+ int fraction, incr, firstFraction, lastFraction;
+ int majorLength;
+ coOrd p0, p1;
+ FLOAT_T sin_aa;
+
+ a = FindAngle( pos0, pos1 );
+ Translate( &pos0, pos0, a, offset );
+ Translate( &pos1, pos1, a, offset );
+ aa = NormalizeAngle(a+(tickSide==0?+90:-90));
+ if (aa > 90.0 && aa < 270.0) {
+#ifdef WINDOWS
+ dyn = -17;
+#else
+ dyn = -12;
+#endif
+ } else {
+ dyn = +3;
+ }
+ sin_aa = sin(D2R(aa));
+ dxn = (long)floor(10.0*sin_aa);
+ end = FindDistance( pos0, pos1 );
+ if (end < 0.1)
+ return;
+ d_orig.x = d->orig.x - 0.001;
+ d_orig.y = d->orig.y - 0.001;
+ d_size.x = d->size.x + 0.002;
+ d_size.y = d->size.y + 0.002;
+ if (!ClipLine( &pos0, &pos1, d_orig, d->angle, d_size ))
+ return;
+
+ start = FindDistance( orig, pos0 );
+ if (offset < 0)
+ start = -start;
+ end = FindDistance( orig, pos1 );
+
+ d->CoOrd2Pix( d, pos0, &x0, &y0 );
+ d->CoOrd2Pix( d, pos1, &x1, &y1 );
+ wDrawLine( d->d, x0, y0, x1, y1,
+ 0, wDrawLineSolid, color, (wDrawOpts)d->funcs->options );
+
+ if (units == UNITS_METRIC) {
+ mm0 = (int)ceil(start*25.4-0.5);
+ mm1 = (int)floor(end*25.4+0.5);
+ len = 2;
+ if (d->scale <= 1) {
+ power = 1;
+ } else if (d->scale <= 8) {
+ power = 10;
+ } else if (d->scale <= 32) {
+ power = 100;
+ } else {
+ power = 1000;
+ }
+ for ( ; power<=1000; power*=10,len+=3 ) {
+ if (power == 1000)
+ len = 10;
+ for (mm=((mm0+(mm0>0?power-1:0))/power)*power; mm<=mm1; mm+=power) {
+ if (power==1000 || mm%(power*10) != 0) {
+ Translate( &p0, orig, a, mm/25.4 );
+ Translate( &p1, p0, aa, len*d->scale/mainD.dpi );
+ d->CoOrd2Pix( d, p0, &x0, &y0 );
+ d->CoOrd2Pix( d, p1, &x1, &y1 );
+ wDrawLine( d->d, x0, y0, x1, y1,
+ 0, wDrawLineSolid, color, (wDrawOpts)d->funcs->options );
+
+ if (!number)
+ continue;
+ if ( (power>=1000) ||
+ (d->scale<=8 && power>=100) ||
+ (d->scale<=1 && power>=10) ) {
+ if (mm%100 != 0) {
+ sprintf(message, "%ld", mm/10%10 );
+ fs = rulerFontSize*2/3;
+ p0.x = p1.x+4*dxn/10*d->scale/mainD.dpi;
+ p0.y = p1.y+dyn*d->scale/mainD.dpi;
+ } else {
+ sprintf(message, "%0.1f", mm/1000.0 );
+ fs = rulerFontSize;
+ p0.x = p0.x+((-(LBORDER-2)/2)+((LBORDER-2)/2+2)*sin_aa)*d->scale/mainD.dpi;
+ p0.y = p1.y+dyn*d->scale/mainD.dpi;
+ }
+ d->CoOrd2Pix( d, p0, &x0, &y0 );
+ wDrawString( d->d, x0, y0, d->angle, message, rulerFp,
+ fs, color, (wDrawOpts)d->funcs->options );
+ }
+ }
+ }
+ }
+ } else {
+ if (d->scale <= 1)
+ incr = 1;
+ else if (d->scale <= 2)
+ incr = 2;
+ else if (d->scale <= 4)
+ incr = 4;
+ else
+ incr = 8;
+ lastInch = (int)floor(end);
+ lastFraction = 7;
+ inch = (int)ceil(start);
+ firstFraction = (((int)((inch-start)*8/*+1*/)) / incr) * incr;
+ if (firstFraction > 0) {
+ inch--;
+ firstFraction = 8 - firstFraction;
+ }
+ for ( ; inch<=lastInch; inch++){
+ if (inch % 12 == 0) {
+ lengths[0] = 10;
+ majorLength = 16;
+ digit = (int)(inch/12);
+ fs = rulerFontSize;
+ quote = '\'';
+ } else if (d->scale <= 8) {
+ lengths[0] = 8;
+ majorLength = 13;
+ digit = (int)(inch%12);
+ fs = rulerFontSize*(2.0/3.0);
+ quote = '"';
+ } else {
+ continue;
+ }
+ if (inch == lastInch)
+ lastFraction = (((int)((end - lastInch)*8)) / incr) * incr;
+ for ( fraction = firstFraction; fraction<=lastFraction; fraction += incr ) {
+ Translate( &p0, orig, a, inch+fraction/8.0 );
+ Translate( &p1, p0, aa, lengths[fraction]*d->scale/72.0 );
+ d->CoOrd2Pix( d, p0, &x0, &y0 );
+ d->CoOrd2Pix( d, p1, &x1, &y1 );
+ wDrawLine( d->d, x0, y0, x1, y1,
+ 0, wDrawLineSolid, color,
+ (wDrawOpts)d->funcs->options );
+#ifdef KLUDGEWINDOWS
+ /* KLUDGE: can't draw invertable strings on windows */
+ if ( (opts&DO_TEMP) == 0)
+#endif
+ if ( fraction == 0 && number == TRUE) {
+ if (inch % 12 == 0 || d->scale <= 2) {
+ Translate( &p0, p0, aa, majorLength*d->scale/72.0 );
+ Translate( &p0, p0, 225, 11*d->scale/72.0 );
+ sprintf(message, "%d%c", digit, quote );
+ d->CoOrd2Pix( d, p0, &x0, &y0 );
+ wDrawString( d->d, x0, y0, d->angle, message, rulerFp, fs, color, (wDrawOpts)d->funcs->options );
+ }
+ }
+ firstFraction = 0;
+ }
+ }
+ }
+}
+
+
+EXPORT void DrawTicks( drawCmd_p d, coOrd size )
+{
+ coOrd p0, p1;
+ DIST_T offset;
+
+ offset = 0.0;
+ if ( d->orig.x<0.0 )
+ offset = d->orig.x;
+ p0.x = 0.0/*d->orig.x*/; p1.x = size.x;
+ p0.y = p1.y = /*max(d->orig.y,0.0)*/ d->orig.y;
+ DrawRuler( d, p0, p1, offset, TRUE, FALSE, borderColor );
+ p0.y = p1.y = min(d->orig.y + d->size.y, size.y);
+ DrawRuler( d, p0, p1, offset, FALSE, TRUE, borderColor );
+ offset = 0.0;
+ if ( d->orig.y<0.0 )
+ offset = d->orig.y;
+ p0.y = 0.0/*d->orig.y*/; p1.y = max(size.y,0.0);
+ p0.x = p1.x = d->orig.x;
+ DrawRuler( d, p0, p1, offset, TRUE, TRUE, borderColor );
+ p0.x = p1.x = min(d->orig.x + d->size.x, size.x);
+ DrawRuler( d, p0, p1, offset, FALSE, FALSE, borderColor );
+}
+
+/*****************************************************************************
+ *
+ * ZOOM and PAN
+ *
+ */
+
+EXPORT coOrd mainCenter;
+
+
+EXPORT void DrawMapBoundingBox( BOOL_T set )
+{
+ if (mainD.d == NULL || mapD.d == NULL)
+ return;
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+}
+
+
+static void ConstraintOrig( coOrd * orig, coOrd size )
+{
+LOG( log_pan, 2, ( "ConstraintOrig [ %0.3f, %0.3f ] RoomSize(%0.3f %0.3f), WxH=%0.3fx%0.3f",
+ orig->x, orig->y, mapD.size.x, mapD.size.y,
+ size.x, size.y ) )
+ if (orig->x+size.x > mapD.size.x ) {
+ orig->x = mapD.size.x-size.x;
+ orig->x += (units==UNITS_ENGLISH?1.0:(1.0/2.54));
+ }
+ if (orig->x < 0)
+ orig->x = 0;
+ if (orig->y+size.y > mapD.size.y ) {
+ orig->y = mapD.size.y-size.y;
+ orig->y += (units==UNITS_ENGLISH?1.0:1.0/2.54);
+
+ }
+ if (orig->y < 0)
+ orig->y = 0;
+ if (mainD.scale >= 1.0) {
+ if (units == UNITS_ENGLISH) {
+ orig->x = floor(orig->x);
+ orig->y = floor(orig->y);
+ } else {
+ orig->x = floor(orig->x*2.54)/2.54;
+ orig->y = floor(orig->y*2.54)/2.54;
+ }
+ }
+ orig->x = (long)(orig->x*pixelBins+0.5)/pixelBins;
+ orig->y = (long)(orig->y*pixelBins+0.5)/pixelBins;
+LOG( log_pan, 2, ( " = [ %0.3f %0.3f ]\n", orig->y, orig->y ) )
+}
+
+/**
+ * Initialize the menu for setting zoom factors.
+ *
+ * \param IN zoomM Menu to which radio button is added
+ * \param IN zoomSubM Second menu to which radio button is added, ignored if NULL
+ *
+ */
+
+EXPORT void InitCmdZoom( wMenu_p zoomM, wMenu_p zoomSubM )
+{
+ int inx;
+
+ for ( inx=0; inx<sizeof zoomList/sizeof zoomList[0]; inx++ ) {
+ if( zoomList[ inx ].value >= 1.0 ) {
+ zoomList[inx].btRadio = wMenuRadioCreate( zoomM, "cmdZoom", zoomList[inx].name, 0, (wMenuCallBack_p)DoZoom, (void *)(&(zoomList[inx].value)));
+ if( zoomSubM )
+ zoomList[inx].pdRadio = wMenuRadioCreate( zoomSubM, "cmdZoom", zoomList[inx].name, 0, (wMenuCallBack_p)DoZoom, (void *)(&(zoomList[inx].value)));
+ }
+ }
+}
+
+/**
+ * Set radio button(s) corresponding to current scale.
+ *
+ * \param IN scale current scale
+ *
+ */
+
+static void SetZoomRadio( DIST_T scale )
+{
+ int inx;
+ long curScale = (long)scale;
+
+ for ( inx=0; inx<sizeof zoomList/sizeof zoomList[0]; inx++ ) {
+ if( curScale == zoomList[inx].value ) {
+
+ wMenuRadioSetActive( zoomList[inx].btRadio );
+ if( zoomList[inx].pdRadio )
+ wMenuRadioSetActive( zoomList[inx].pdRadio );
+
+ /* activate / deactivate zoom buttons when appropriate */
+ wControlLinkedActive( (wControl_p)zoomUpB, ( inx != 0 ) );
+ wControlLinkedActive( (wControl_p)zoomDownB, ( inx < (sizeof zoomList/sizeof zoomList[0] - 1)));
+ }
+ }
+}
+
+/**
+ * Find current scale
+ *
+ * \param IN scale current scale
+ * \return index in scale table or -1 if error
+ *
+ */
+
+static int ScaleInx( DIST_T scale )
+{
+ int inx;
+
+ for ( inx=0; inx<sizeof zoomList/sizeof zoomList[0]; inx++ ) {
+ if( scale == zoomList[inx].value ) {
+ return inx;
+ }
+ }
+ return -1;
+}
+
+/**
+ * Set up for new drawing scale. After the scale was changed, eg. via zoom button, everything
+ * is set up for the new scale.
+ *
+ * \param scale IN new scale
+ */
+
+static void DoNewScale( DIST_T scale )
+{
+ char tmp[20];
+
+ if (scale > MAX_MAIN_SCALE)
+ scale = MAX_MAIN_SCALE;
+
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+#ifdef LATER
+ center.x = mainD.orig.x + mainD.size.x/2.0;
+ center.y = mainD.orig.y + mainD.size.y/2.0;
+#endif
+ tempD.scale = mainD.scale = scale;
+ mainD.dpi = wDrawGetDPI( mainD.d );
+ if ( mainD.dpi == 75 ) {
+ mainD.dpi = 72.0;
+ } else if ( scale > 1.0 && scale <= 12.0 ) {
+ mainD.dpi = floor( (mainD.dpi + scale/2)/scale) * scale;
+ }
+ tempD.dpi = mainD.dpi;
+
+ SetZoomRadio( scale );
+ InfoScale();
+ SetMainSize();
+ mainD.orig.x = mainCenter.x - mainD.size.x/2.0;
+ mainD.orig.y = mainCenter.y - mainD.size.y/2.0;
+ ConstraintOrig( &mainD.orig, mainD.size );
+ MainRedraw();
+ tempD.orig = mainD.orig;
+LOG( log_zoom, 1, ( "center = [%0.3f %0.3f]\n", mainCenter.x, mainCenter.y ) )
+ /*SetFont(0);*/
+ sprintf( tmp, "%0.3f", mainD.scale );
+ wPrefSetString( "draw", "zoom", tmp );
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ if (recordF) {
+ fprintf( recordF, "ORIG %0.3f %0.3f %0.3f\n",
+ mainD.scale, mainD.orig.x, mainD.orig.y );
+ }
+}
+
+
+/**
+ * User selected zoom in, via mouse wheel, button or pulldown.
+ *
+ * \param mode IN FALSE if zoom button was activated, TRUE if activated via popup or mousewheel
+ */
+
+EXPORT void DoZoomUp( void * mode )
+{
+ long newScale;
+ int i;
+
+ if ( mode != NULL || (MyGetKeyState()&WKEY_SHIFT) == 0 ) {
+ i = ScaleInx( mainD.scale );
+ /*
+ * Zooming into macro mode happens when we are at scale 1:1.
+ * To jump into macro mode, the CTRL-key has to be pressed and held.
+ */
+ if( mainD.scale != 1.0 || (mainD.scale == 1.0 && (MyGetKeyState()&WKEY_CTRL))) {
+ if( i )
+ DoNewScale( zoomList[ i - 1 ].value );
+ }
+ } else if ( (MyGetKeyState()&WKEY_CTRL) == 0 ) {
+ wPrefGetInteger( "misc", "zoomin", &newScale, 4 );
+ DoNewScale( newScale );
+ } else {
+ wPrefSetInteger( "misc", "zoomin", (long)mainD.scale );
+ InfoMessage( _("Zoom In Program Value %ld:1"), (long)mainD.scale );
+ }
+}
+
+
+/**
+ * User selected zoom out, via mouse wheel, button or pulldown.
+ *
+ * \param mode IN FALSE if zoom button was activated, TRUE if activated via popup or mousewheel
+ */
+
+EXPORT void DoZoomDown( void * mode)
+{
+ long newScale;
+ int i;
+
+ if ( mode != NULL || (MyGetKeyState()&WKEY_SHIFT) == 0 ) {
+ i = ScaleInx( mainD.scale );
+ if( i>= 0 && i < ( sizeof zoomList/sizeof zoomList[0] - 1 ))
+ DoNewScale( zoomList[ i + 1 ].value );
+
+ } else if ( (MyGetKeyState()&WKEY_CTRL) == 0 ) {
+ wPrefGetInteger( "misc", "zoomout", &newScale, 16 );
+ DoNewScale( newScale );
+ } else {
+ wPrefSetInteger( "misc", "zoomout", (long)mainD.scale );
+ InfoMessage( _("Zoom Out Program Value %ld:1"), (long)mainD.scale );
+ }
+}
+
+/**
+ * Zoom to user selected value. This is the callback function for the
+ * user-selectable preset zoom values.
+ *
+ * \param IN scale current pScale
+ *
+ */
+
+EXPORT void DoZoom( DIST_T *pScale )
+{
+ DIST_T scale = *pScale;
+
+ if( scale != mainD.scale )
+ DoNewScale( scale );
+}
+
+
+
+EXPORT void Pix2CoOrd(
+ drawCmd_p d,
+ wPos_t x,
+ wPos_t y,
+ coOrd * pos )
+{
+ pos->x = (((DIST_T)x)/d->dpi)*d->scale+d->orig.x;
+ pos->y = (((DIST_T)y)/d->dpi)*d->scale+d->orig.y;
+}
+
+EXPORT void CoOrd2Pix(
+ drawCmd_p d,
+ coOrd pos,
+ wPos_t * x,
+ wPos_t * y )
+{
+ *x = (wPos_t)((pos.x-d->orig.x)/d->scale*d->dpi);
+ *y = (wPos_t)((pos.y-d->orig.y)/d->scale*d->dpi);
+}
+
+
+static void DoMapPan( wAction_t action, coOrd pos )
+{
+ static coOrd mapOrig;
+ static coOrd oldOrig, newOrig;
+ static coOrd size;
+ static DIST_T xscale, yscale;
+ static enum { noPan, movePan, resizePan } mode = noPan;
+ wPos_t x, y;
+
+ switch (action & 0xFF) {
+
+ case C_DOWN:
+ if ( mode == noPan )
+ mode = movePan;
+ else
+ break;
+ mapOrig = pos;
+ size = mainD.size;
+ newOrig = oldOrig = mainD.orig;
+LOG( log_pan, 1, ( "ORIG = [ %0.3f, %0.3f ]\n", mapOrig.x, mapOrig.y ) )
+ break;
+ case C_MOVE:
+ if ( mode != movePan )
+ break;
+ DrawHilight( &mapD, newOrig, size );
+LOG( log_pan, 2, ( "NEW = [ %0.3f, %0.3f ] \n", pos.x, pos.y ) )
+ newOrig.x = oldOrig.x + pos.x-mapOrig.x;
+ newOrig.y = oldOrig.y + pos.y-mapOrig.y;
+ ConstraintOrig( &newOrig, mainD.size );
+ if (liveMap) {
+ tempD.orig = mainD.orig = newOrig;
+ MainRedraw();
+ }
+ DrawHilight( &mapD, newOrig, size );
+ break;
+ case C_UP:
+ if ( mode != movePan )
+ break;
+ tempD.orig = mainD.orig = newOrig;
+ mainCenter.x = newOrig.x + mainD.size.x/2.0;
+ mainCenter.y = newOrig.y + mainD.size.y/2.0;
+ if (!liveMap)
+ MainRedraw();
+LOG( log_pan, 1, ( "FINAL = [ %0.3f, %0.3f ]\n", pos.x, pos.y ) )
+#ifdef LATER
+ if (recordF) {
+ fprintf( recordF, "ORIG %0.3f %0.3f %0.3f\n",
+ mainD.scale, mainD.orig.x, mainD.orig.y );
+ }
+#endif
+ mode = noPan;
+ break;
+
+ case C_RDOWN:
+ if ( mode == noPan )
+ mode = resizePan;
+ else
+ break;
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ newOrig = pos;
+ oldOrig = newOrig;
+#ifdef LATER
+ xscale = INIT_MAP_SCALE;
+ size.x = mapD.size.x/xscale;
+ size.y = mapD.size.y/xscale;
+#endif
+ xscale = 1;
+ size.x = mainD.size.x/mainD.scale;
+ size.y = mainD.size.y/mainD.scale;
+ newOrig.x -= size.x/2.0;
+ newOrig.y -= size.y/2.0;
+ DrawHilight( &mapD, newOrig, size );
+ break;
+
+ case C_RMOVE:
+ if ( mode != resizePan )
+ break;
+ DrawHilight( &mapD, newOrig, size );
+ if (pos.x < 0)
+ pos.x = 0;
+ if (pos.x > mapD.size.x)
+ pos.x = mapD.size.x;
+ if (pos.y < 0)
+ pos.y = 0;
+ if (pos.y > mapD.size.y)
+ pos.y = mapD.size.y;
+ size.x = (pos.x - oldOrig.x)*2.0;
+ size.y = (pos.y - oldOrig.y)*2.0;
+ if (size.x < 0) {
+ size.x = - size.x;
+ }
+ if (size.y < 0) {
+ size.y = - size.y;
+ }
+ xscale = size.x / (mainD.size.x/mainD.scale);
+ yscale = size.y / (mainD.size.y/mainD.scale);
+ if (xscale < yscale)
+ xscale = yscale;
+ xscale = ceil( xscale );
+ if (xscale < 1)
+ xscale = 1;
+ if (xscale > 64)
+ xscale = 64;
+ size.x = (mainD.size.x/mainD.scale) * xscale;
+ size.y = (mainD.size.y/mainD.scale) * xscale;
+ newOrig = oldOrig;
+ newOrig.x -= size.x/2.0;
+ newOrig.y -= size.y/2.0;
+ DrawHilight( &mapD, newOrig, size );
+ break;
+
+ case C_RUP:
+ if ( mode != resizePan )
+ break;
+ tempD.size = mainD.size = size;
+ tempD.orig = mainD.orig = newOrig;
+ mainCenter.x = newOrig.x + mainD.size.x/2.0;
+ mainCenter.y = newOrig.y + mainD.size.y/2.0;
+ DoNewScale( xscale );
+ mode = noPan;
+ break;
+
+ case wActionExtKey:
+ mainD.CoOrd2Pix(&mainD,pos,&x,&y);
+ switch ((wAccelKey_e)(action>>8)) {
+#ifndef WINDOWS
+ case wAccelKey_Pgdn:
+ DoZoomUp(NULL);
+ return;
+ case wAccelKey_Pgup:
+ DoZoomDown(NULL);
+ return;
+ case wAccelKey_F5:
+ MainRedraw();
+ return;
+#endif
+ case wAccelKey_Right:
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ mainD.orig.x += mainD.size.x/2;
+ ConstraintOrig( &mainD.orig, mainD.size );
+ mainCenter.x = mainD.orig.x + mainD.size.x/2.0;
+ mainCenter.y = mainD.orig.y + mainD.size.y/2.0;
+ MainRedraw();
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ break;
+ case wAccelKey_Left:
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ mainD.orig.x -= mainD.size.x/2;
+ ConstraintOrig( &mainD.orig, mainD.size );
+ mainCenter.x = mainD.orig.x + mainD.size.x/2.0;
+ mainCenter.y = mainD.orig.y + mainD.size.y/2.0;
+ MainRedraw();
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ break;
+ case wAccelKey_Up:
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ mainD.orig.y += mainD.size.y/2;
+ ConstraintOrig( &mainD.orig, mainD.size );
+ mainCenter.x = mainD.orig.x + mainD.size.x/2.0;
+ mainCenter.y = mainD.orig.y + mainD.size.y/2.0;
+ MainRedraw();
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ break;
+ case wAccelKey_Down:
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ mainD.orig.y -= mainD.size.y/2;
+ ConstraintOrig( &mainD.orig, mainD.size );
+ mainCenter.x = mainD.orig.x + mainD.size.x/2.0;
+ mainCenter.y = mainD.orig.y + mainD.size.y/2.0;
+ MainRedraw();
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ break;
+ default:
+ return;
+ }
+ mainD.Pix2CoOrd( &mainD, x, y, &pos );
+ InfoPos( pos );
+ return;
+ default:
+ return;
+ }
+}
+
+
+EXPORT BOOL_T IsClose(
+ DIST_T d )
+{
+ wPos_t pd;
+ pd = (wPos_t)(d/mainD.scale * mainD.dpi);
+ return pd <= closePixels;
+}
+
+/*****************************************************************************
+ *
+ * MAIN MOUSE HANDLER
+ *
+ */
+
+static int ignoreMoves = 1;
+
+EXPORT void ResetMouseState( void )
+{
+ mouseState = mouseNone;
+}
+
+
+EXPORT void FakeDownMouseState( void )
+{
+ mouseState = mouseLeftPending;
+}
+
+/**
+ * Return the current position of the mouse pointer in drawing coordinates.
+ *
+ * \param x OUT pointer x position
+ * \param y OUT pointer y position
+ * \return
+ */
+
+void
+GetMousePosition( int *x, int *y )
+{
+ if( x && y ) {
+ *x = mousePositionx;
+ *y = mousePositiony;
+ }
+}
+
+static void DoMouse( wAction_t action, coOrd pos )
+{
+
+ BOOL_T rc;
+ wPos_t x, y;
+ static BOOL_T ignoreCommands;
+
+ LOG( log_mouse, 2, ( "DoMouse( %d, %0.3f, %0.3f )\n", action, pos.x, pos.y ) )
+
+ if (recordF) {
+ RecordMouse( "MOUSE", action, pos.x, pos.y );
+ }
+
+ switch (action&0xFF) {
+ case C_UP:
+ if (mouseState != mouseLeft)
+ return;
+ if (ignoreCommands) {
+ ignoreCommands = FALSE;
+ return;
+ }
+ mouseState = mouseNone;
+ break;
+ case C_RUP:
+ if (mouseState != mouseRight)
+ return;
+ if (ignoreCommands) {
+ ignoreCommands = FALSE;
+ return;
+ }
+ mouseState = mouseNone;
+ break;
+ case C_MOVE:
+ if (mouseState == mouseLeftPending ) {
+ action = C_DOWN;
+ mouseState = mouseLeft;
+ }
+ if (mouseState != mouseLeft)
+ return;
+ if (ignoreCommands)
+ return;
+ break;
+ case C_RMOVE:
+ if (mouseState != mouseRight)
+ return;
+ if (ignoreCommands)
+ return;
+ break;
+ case C_DOWN:
+ mouseState = mouseLeft;
+ break;
+ case C_RDOWN:
+ mouseState = mouseRight;
+ break;
+ }
+
+ inError = FALSE;
+ if ( deferSubstituteControls[0] )
+ InfoSubstituteControls( deferSubstituteControls, deferSubstituteLabels );
+
+ switch ( action&0xFF ) {
+ case C_DOWN:
+ case C_RDOWN:
+ tempSegs_da.cnt = 0;
+ break;
+ case wActionMove:
+ InfoPos( pos );
+ if ( ignoreMoves )
+ return;
+ break;
+ case wActionExtKey:
+ mainD.CoOrd2Pix(&mainD,pos,&x,&y);
+ switch ((wAccelKey_e)(action>>8)) {
+ case wAccelKey_Del:
+ SelectDelete();
+ return;
+#ifndef WINDOWS
+ case wAccelKey_Pgdn:
+ DoZoomUp(NULL);
+ break;
+ case wAccelKey_Pgup:
+ DoZoomDown(NULL);
+ break;
+#endif
+ case wAccelKey_Right:
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ mainD.orig.x += mainD.size.x/2;
+ ConstraintOrig( &mainD.orig, mainD.size );
+ mainCenter.x = mainD.orig.x + mainD.size.x/2.0;
+ mainCenter.y = mainD.orig.y + mainD.size.y/2.0;
+ MainRedraw();
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ break;
+ case wAccelKey_Left:
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ mainD.orig.x -= mainD.size.x/2;
+ ConstraintOrig( &mainD.orig, mainD.size );
+ mainCenter.x = mainD.orig.x + mainD.size.x/2.0;
+ mainCenter.y = mainD.orig.y + mainD.size.y/2.0;
+ MainRedraw();
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ break;
+ case wAccelKey_Up:
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ mainD.orig.y += mainD.size.y/2;
+ ConstraintOrig( &mainD.orig, mainD.size );
+ mainCenter.x = mainD.orig.x + mainD.size.x/2.0;
+ mainCenter.y = mainD.orig.y + mainD.size.y/2.0;
+ MainRedraw();
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ break;
+ case wAccelKey_Down:
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ mainD.orig.y -= mainD.size.y/2;
+ ConstraintOrig( &mainD.orig, mainD.size );
+ mainCenter.x = mainD.orig.x + mainD.size.x/2.0;
+ mainCenter.y = mainD.orig.y + mainD.size.y/2.0;
+ MainRedraw();
+ DrawHilight( &mapD, mainD.orig, mainD.size );
+ break;
+ default:
+ return;
+ }
+ mainD.Pix2CoOrd( &mainD, x, y, &pos );
+ InfoPos( pos );
+ return;
+ case C_TEXT:
+ if ((action>>8) == 0x0D)
+ action = C_OK;
+ else if ((action>>8) == 0x1B) {
+ ConfirmReset( TRUE );
+ return;
+ }
+ case C_MOVE:
+ case C_UP:
+ case C_RMOVE:
+ case C_RUP:
+ InfoPos( pos );
+ /*DrawTempTrack();*/
+ break;
+ case C_WUP:
+ DoZoomUp((void *)1L);
+ break;
+ case C_WDOWN:
+ DoZoomDown((void *)1L);
+ break;
+ default:
+ NoticeMessage( MSG_DOMOUSE_BAD_OP, _("Ok"), NULL, action&0xFF );
+ break;
+ }
+ if (delayUpdate)
+ wDrawDelayUpdate( mainD.d, TRUE );
+ rc = DoCurCommand( action, pos );
+ wDrawDelayUpdate( mainD.d, FALSE );
+ switch( rc ) {
+ case C_CONTINUE:
+ /*DrawTempTrack();*/
+ break;
+ case C_ERROR:
+ ignoreCommands = TRUE;
+ inError = TRUE;
+ Reset();
+ LOG( log_mouse, 1, ( "Mouse returns Error\n" ) )
+ break;
+ case C_TERMINATE:
+ Reset();
+ DoCurCommand( C_START, zero );
+ break;
+ case C_INFO:
+ Reset();
+ break;
+ }
+}
+
+
+wPos_t autoPanFactor = 10;
+static void DoMousew( wDraw_p d, void * context, wAction_t action, wPos_t x, wPos_t y )
+{
+ coOrd pos;
+ coOrd orig;
+ wPos_t w, h;
+ static wPos_t lastX, lastY;
+ DIST_T minDist;
+
+ if ( autoPan && !inPlayback ) {
+ wDrawGetSize( mainD.d, &w, &h );
+ if ( action == wActionLDown || action == wActionRDown ||
+ (action == wActionLDrag && mouseState == mouseLeftPending ) /*||
+ (action == wActionRDrag && mouseState == mouseRightPending ) */ ) {
+ lastX = x;
+ lastY = y;
+ }
+ if ( action == wActionLDrag || action == wActionRDrag ) {
+ orig = mainD.orig;
+ if ( ( x < 10 && x < lastX ) ||
+ ( x > w-10 && x > lastX ) ||
+ ( y < 10 && y < lastY ) ||
+ ( y > h-10 && y > lastY ) ) {
+ mainD.Pix2CoOrd( &mainD, x, y, &pos );
+ orig.x = mainD.orig.x + (pos.x - (mainD.orig.x + mainD.size.x/2.0) )/autoPanFactor;
+ orig.y = mainD.orig.y + (pos.y - (mainD.orig.y + mainD.size.y/2.0) )/autoPanFactor;
+ if ( orig.x != mainD.orig.x || orig.y != mainD.orig.y ) {
+ if ( mainD.scale >= 1 ) {
+ if ( units == UNITS_ENGLISH )
+ minDist = 1.0;
+ else
+ minDist = 1.0/2.54;
+ if ( orig.x != mainD.orig.x ) {
+ if ( fabs( orig.x-mainD.orig.x ) < minDist ) {
+ if ( orig.x < mainD.orig.x )
+ orig.x -= minDist;
+ else
+ orig.x += minDist;
+ }
+ }
+ if ( orig.y != mainD.orig.y ) {
+ if ( fabs( orig.y-mainD.orig.y ) < minDist ) {
+ if ( orig.y < mainD.orig.y )
+ orig.y -= minDist;
+ else
+ orig.y += minDist;
+ }
+ }
+ }
+ ConstraintOrig( &orig, mainD.size );
+ if ( orig.x != mainD.orig.x || orig.y != mainD.orig.y ) {
+ DrawMapBoundingBox( FALSE );
+ mainD.orig = orig;
+ MainRedraw();
+ /*DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack );*/
+ DrawMapBoundingBox( TRUE );
+ wFlush();
+ }
+ }
+ }
+ lastX = x;
+ lastY = y;
+ }
+ }
+ mainD.Pix2CoOrd( &mainD, x, y, &pos );
+ mousePositionx = x;
+ mousePositiony = y;
+
+ DoMouse( action, pos );
+}
+
+static wBool_t PlaybackMain( char * line )
+{
+ int rc;
+ int action;
+ coOrd pos;
+ char *oldLocale = NULL;
+
+ oldLocale = SaveLocale("C");
+ rc=sscanf( line, "%d " SCANF_FLOAT_FORMAT SCANF_FLOAT_FORMAT, &action, &pos.x, &pos.y);
+ RestoreLocale(oldLocale);
+
+ if (rc != 3) {
+ SyntaxError( "MOUSE", rc, 3 );
+ } else {
+ PlaybackMouse( DoMouse, &mainD, (wAction_t)action, pos, wDrawColorBlack );
+ }
+ return TRUE;
+}
+
+/*****************************************************************************
+ *
+ * INITIALIZATION
+ *
+ */
+
+static paramDrawData_t mapDrawData = { 100, 100, (wDrawRedrawCallBack_p)MapRedraw, DoMapPan, &mapD };
+static paramData_t mapPLs[] = {
+ { PD_DRAW, NULL, "canvas", 0, &mapDrawData } };
+static paramGroup_t mapPG = { "map", PGO_NODEFAULTPROC, mapPLs, sizeof mapPLs/sizeof mapPLs[0] };
+
+static void MapDlgUpdate(
+ paramGroup_p pg,
+ int inx,
+ void * valueP )
+{
+ if ( inx == -1 ) {
+ mapVisible = FALSE;
+ }
+}
+
+
+static void DrawChange( long changes )
+{
+ if (changes & CHANGE_MAIN)
+ MainRedraw();
+ if (changes &CHANGE_UNITS)
+ SetInfoBar();
+ if (changes & CHANGE_MAP)
+ MapResize();
+}
+
+
+EXPORT void DrawInit( int initialZoom )
+{
+ wPos_t w, h;
+
+ wWinGetSize( mainW, &w, &h );
+ /*LayoutToolBar();*/
+ h -= toolbarHeight+infoHeight;
+ if ( w <= 0 ) w = 1;
+ if ( h <= 0 ) h = 1;
+ tempD.d = mainD.d = wDrawCreate( mainW, 0, toolbarHeight, "", BD_TICKS,
+ w, h, &mainD,
+ (wDrawRedrawCallBack_p)MainRedraw, DoMousew );
+
+ if (initialZoom == 0) {
+ WDOUBLE_T tmpR;
+ wPrefGetFloat( "draw", "zoom", &tmpR, mainD.scale );
+ mainD.scale = tmpR;
+ } else {
+ while (initialZoom > 0 && mainD.scale < MAX_MAIN_SCALE) {
+ mainD.scale *= 2;
+ initialZoom--;
+ }
+ while (initialZoom < 0 && mainD.scale > MIN_MAIN_SCALE) {
+ mainD.scale /= 2;
+ initialZoom++;
+ }
+ }
+ tempD.scale = mainD.scale;
+ mainD.dpi = wDrawGetDPI( mainD.d );
+ if ( mainD.dpi == 75 ) {
+ mainD.dpi = 72.0;
+ } else if ( mainD.scale > 1.0 && mainD.scale <= 12.0 ) {
+ mainD.dpi = floor( (mainD.dpi + mainD.scale/2)/mainD.scale) * mainD.scale;
+ }
+ tempD.dpi = mainD.dpi;
+
+ SetMainSize();
+ mapD.scale = mapScale;
+ /*w = (wPos_t)((mapD.size.x/mapD.scale)*mainD.dpi + 0.5)+2;*/
+ /*h = (wPos_t)((mapD.size.y/mapD.scale)*mainD.dpi + 0.5)+2;*/
+ ParamRegister( &mapPG );
+ mapW = ParamCreateDialog( &mapPG, MakeWindowTitle(_("Map")), NULL, NULL, NULL, FALSE, NULL, 0, MapDlgUpdate );
+ ChangeMapScale();
+
+ log_pan = LogFindIndex( "pan" );
+ log_zoom = LogFindIndex( "zoom" );
+ log_mouse = LogFindIndex( "mouse" );
+ AddPlaybackProc( "MOUSE ", (playbackProc_p)PlaybackMain, NULL );
+
+ rulerFp = wStandardFont( F_HELV, FALSE, FALSE );
+
+ SetZoomRadio( mainD.scale );
+ InfoScale();
+ SetInfoBar();
+ InfoPos( zero );
+ RegisterChangeNotification( DrawChange );
+#ifdef LATER
+ wAttachAccelKey( wAccelKey_Pgup, 0, (wAccelKeyCallBack_p)doZoomUp, NULL );
+ wAttachAccelKey( wAccelKey_Pgdn, 0, (wAccelKeyCallBack_p)doZoomDown, NULL );
+#endif
+}