/** \file cdraw.c * Drawing of geometric elements */ /* 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 #include #include #include "ccurve.h" #include "cbezier.h" #include "drawgeom.h" #include "fileio.h" #include "i18n.h" #include "messages.h" #include "param.h" #include "track.h" #include "utility.h" #include "misc.h" extern TRKTYP_T T_BZRLIN; extern void wSetSelectedFontSize(int size); static long fontSizeList[] = { 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 90, 100, 120, 140, 160, 180, 200, 250, 300, 350, 400, 450, 500 }; EXPORT void LoadFontSizeList( wList_p list, long curFontSize) { wIndex_t curInx = 0, inx1; int inx; wListClear(list); for (inx = 0; inx < sizeof fontSizeList / sizeof fontSizeList[0]; inx++) { if ((inx == 0 || curFontSize > fontSizeList[inx - 1]) && (curFontSize < fontSizeList[inx])) { sprintf(message, "%ld", curFontSize); curInx = wListAddValue(list, message, NULL, (void*)curFontSize); } sprintf(message, "%ld", fontSizeList[inx]); inx1 = wListAddValue(list, message, NULL, (void*)fontSizeList[inx]); if (curFontSize == fontSizeList[inx]) curInx = inx1; } if (curFontSize > fontSizeList[(sizeof fontSizeList / sizeof fontSizeList[0]) - 1]) { sprintf(message, "%ld", curFontSize); curInx = wListAddValue(list, message, NULL, (void*)curFontSize); } wListSetIndex(list, curInx); wFlush(); } long GetFontSize(wIndex_t inx) { return(fontSizeList[inx]); } long GetFontSizeIndex(long size) { int i; for (i = 0; i < sizeof fontSizeList / sizeof fontSizeList[0]; i++) { if (fontSizeList[i] == size) return(i); } return(-1); } EXPORT void UpdateFontSizeList( long * fontSizeR, wList_p list, wIndex_t listInx ) { long fontSize; if ( listInx >= 0 ) { *fontSizeR = (long)wListGetItemContext( list, listInx ); } else { wListGetValues( list, message, sizeof message, NULL, NULL ); if ( message[0] != '\0' ) { fontSize = atol( message ); if ( fontSize <= 0 ) { NoticeMessage( _("Font Size must be > 0"), _("Ok"), NULL ); sprintf( message, "%ld", *fontSizeR ); wListSetValue( list, message ); } else { if ( fontSize <= 500 || NoticeMessage( MSG_LARGE_FONT, _("Yes"), _("No") ) > 0 ) { *fontSizeR = fontSize; /* inform gtkfont dialog from change */ wSetSelectedFontSize((int)fontSize); /*LoadFontSizeList( list, *fontSizeR );*/ } else { sprintf( message, "%ld", *fontSizeR ); wListSetValue( list, message ); } } } } } /******************************************************************************* * * DRAW * */ struct extraData { coOrd orig; ANGLE_T angle; wIndex_t segCnt; trkSeg_t segs[1]; }; static TRKTYP_T T_DRAW = -1; static track_p ignoredTableEdge; static track_p ignoredDraw; static void ComputeDrawBoundingBox( track_p t ) { struct extraData * xx = GetTrkExtraData(t); coOrd lo, hi; GetSegBounds( xx->orig, xx->angle, xx->segCnt, xx->segs, &lo, &hi ); hi.x += lo.x; hi.y += lo.y; SetBoundingBox( t, hi, lo ); } static track_p MakeDrawFromSeg1( wIndex_t index, coOrd pos, ANGLE_T angle, trkSeg_p sp ) { struct extraData * xx; track_p trk; if ( sp->type == ' ' ) return NULL; trk = NewTrack( index, T_DRAW, 0, sizeof *xx ); xx = GetTrkExtraData( trk ); xx->orig = pos; xx->angle = angle; xx->segCnt = 1; memcpy( xx->segs, sp, sizeof *(trkSeg_p)0 ); if (xx->segs[0].type == SEG_POLY || xx->segs[0].type == SEG_FILPOLY) { xx->segs[0].u.p.pts = (coOrd*)MyMalloc( (sp->u.p.cnt) * sizeof (coOrd) ); memcpy(xx->segs[0].u.p.pts, sp->u.p.pts, sp->u.p.cnt * sizeof (coOrd) ); } if (xx->segs[0].type == SEG_TEXT) { xx->segs[0].u.t.string = MyStrdup(sp->u.t.string); } ComputeDrawBoundingBox( trk ); return trk; } EXPORT track_p MakeDrawFromSeg( coOrd pos, ANGLE_T angle, trkSeg_p sp ) { return MakeDrawFromSeg1( 0, pos, angle, sp ); } static DIST_T DistanceDraw( track_p t, coOrd * p ) { struct extraData * xx = GetTrkExtraData(t); if ( ignoredTableEdge == t && xx->segs[0].type == SEG_TBLEDGE ) return 100000.0; if ( ignoredDraw == t ) return 100000.0; return DistanceSegs( xx->orig, xx->angle, xx->segCnt, xx->segs, p, NULL ); } static struct { coOrd endPt[2]; FLOAT_T length; coOrd center; DIST_T radius; ANGLE_T angle0; ANGLE_T angle1; ANGLE_T angle; long pointCount; long lineWidth; wDrawColor color; wIndex_t benchChoice; wIndex_t benchOrient; wIndex_t dimenSize; descPivot_t pivot; wIndex_t fontSizeInx; char text[STR_LONG_SIZE]; unsigned int layer; char polyType[STR_SIZE]; } drawData; typedef enum { E0, E1, CE, RA, LN, AL, A1, A2, VC, LW, CO, BE, OR, DS, TP, TA, TS, TX, PV, LY, PT } drawDesc_e; static descData_t drawDesc[] = { /*E0*/ { DESC_POS, N_("End Pt 1: X,Y"), &drawData.endPt[0] }, /*E1*/ { DESC_POS, N_("End Pt 2: X,Y"), &drawData.endPt[1] }, /*CE*/ { DESC_POS, N_("Center: X,Y"), &drawData.center }, /*RA*/ { DESC_DIM, N_("Radius"), &drawData.radius }, /*LN*/ { DESC_DIM, N_("Length"), &drawData.length }, /*AL*/ { DESC_FLOAT, N_("Angle"), &drawData.angle }, /*A1*/ { DESC_ANGLE, N_("CCW Angle"), &drawData.angle0 }, /*A2*/ { DESC_ANGLE, N_("CW Angle"), &drawData.angle1 }, /*VC*/ { DESC_LONG, N_("Point Count"), &drawData.pointCount }, /*LW*/ { DESC_LONG, N_("Line Width"), &drawData.lineWidth }, /*CO*/ { DESC_COLOR, N_("Color"), &drawData.color }, /*BE*/ { DESC_LIST, N_("Lumber"), &drawData.benchChoice }, /*OR*/ { DESC_LIST, N_("Orientation"), &drawData.benchOrient }, /*DS*/ { DESC_LIST, N_("Size"), &drawData.dimenSize }, /*TP*/ { DESC_POS, N_("Origin: X,Y"), &drawData.endPt[0] }, /*TA*/ { DESC_FLOAT, N_("Angle"), &drawData.angle }, /*TS*/ { DESC_EDITABLELIST, N_("Font Size"), &drawData.fontSizeInx }, /*TX*/ { DESC_TEXT, N_("Text"), &drawData.text }, /*PV*/ { DESC_PIVOT, N_("Pivot"), &drawData.pivot }, /*LY*/ { DESC_LAYER, N_("Layer"), &drawData.layer }, /*PT*/ { DESC_STRING, N_("Type"), &drawData.polyType }, { DESC_NULL } }; int drawSegInx; #define UNREORIGIN( Q, P, A, O ) { \ (Q) = (P); \ (Q).x -= (O).x; \ (Q).y -= (O).y; \ if ( (A) != 0.0 ) \ Rotate( &(Q), zero, -(A) ); \ } static void UpdateDraw( track_p trk, int inx, descData_p descUpd, BOOL_T final ) { struct extraData *xx = GetTrkExtraData(trk); trkSeg_p segPtr; coOrd mid; long fontSize; if ( drawSegInx==-1 ) return; segPtr = &xx->segs[drawSegInx]; if ( inx == -1 ) { if (segPtr->type != SEG_TEXT) return; else inx = TX; //Always look at TextField for SEG_TEXT on "Done" } MainRedraw(); MapRedraw(); UndrawNewTrack( trk ); switch ( inx ) { case LW: segPtr->width = drawData.lineWidth/mainD.dpi; break; case CO: segPtr->color = drawData.color; break; case E0: case E1: if ( inx == E0 ) { UNREORIGIN( segPtr->u.l.pos[0], drawData.endPt[0], xx->angle, xx->orig ); } else { UNREORIGIN( segPtr->u.l.pos[1], drawData.endPt[1], xx->angle, xx->orig ); } drawData.length = FindDistance( drawData.endPt[0], drawData.endPt[1] ); drawData.angle = FindAngle( drawData.endPt[0], drawData.endPt[1] ); drawDesc[LN].mode |= DESC_CHANGE; drawDesc[AL].mode |= DESC_CHANGE; break; case LN: case AL: if ( segPtr->type == SEG_CRVLIN && inx == AL ) { if ( drawData.angle <= 0.0 || drawData.angle >= 360.0 ) { ErrorMessage( MSG_CURVE_OUT_OF_RANGE ); drawData.angle = segPtr->u.c.a1; drawDesc[AL].mode |= DESC_CHANGE; break; } } else { if ( drawData.length <= minLength ) { ErrorMessage( MSG_OBJECT_TOO_SHORT ); if ( segPtr->type != SEG_CRVLIN ) { drawData.length = FindDistance( drawData.endPt[0], drawData.endPt[1] ); } else { drawData.length = fabs(segPtr->u.c.radius)*2*M_PI*segPtr->u.c.a1/360.0; } drawDesc[LN].mode |= DESC_CHANGE; break; } } if ( segPtr->type != SEG_CRVLIN ) { switch ( drawData.pivot ) { case DESC_PIVOT_FIRST: Translate( &drawData.endPt[1], drawData.endPt[0], drawData.angle, drawData.length ); UNREORIGIN( segPtr->u.l.pos[1], drawData.endPt[1], xx->angle, xx->orig ); drawDesc[E1].mode |= DESC_CHANGE; break; case DESC_PIVOT_SECOND: Translate( &drawData.endPt[0], drawData.endPt[1], drawData.angle+180.0, drawData.length ); UNREORIGIN( segPtr->u.l.pos[0], drawData.endPt[0], xx->angle, xx->orig ); drawDesc[E0].mode |= DESC_CHANGE; break; case DESC_PIVOT_MID: mid.x = (drawData.endPt[0].x+drawData.endPt[1].x)/2.0; mid.y = (drawData.endPt[0].y+drawData.endPt[1].y)/2.0; Translate( &drawData.endPt[0], mid, drawData.angle+180.0, drawData.length/2.0 ); Translate( &drawData.endPt[1], mid, drawData.angle, drawData.length/2.0 ); UNREORIGIN( segPtr->u.l.pos[0], drawData.endPt[0], xx->angle, xx->orig ); UNREORIGIN( segPtr->u.l.pos[1], drawData.endPt[1], xx->angle, xx->orig ); drawDesc[E0].mode |= DESC_CHANGE; drawDesc[E1].mode |= DESC_CHANGE; break; default: break; } } else { if ( drawData.angle < 0.0 || drawData.angle >= 360.0 ) { ErrorMessage( MSG_CURVE_OUT_OF_RANGE ); drawData.angle = segPtr->u.c.a1; drawDesc[AL].mode |= DESC_CHANGE; } else { segPtr->u.c.a0 = NormalizeAngle( segPtr->u.c.a0+segPtr->u.c.a1/2.0-drawData.angle/2.0); segPtr->u.c.a1 = drawData.angle; drawData.angle0 = NormalizeAngle( segPtr->u.c.a0+xx->angle ); drawData.angle1 = NormalizeAngle( drawData.angle0+segPtr->u.c.a1 ); drawDesc[A1].mode |= DESC_CHANGE; drawDesc[A2].mode |= DESC_CHANGE; } } break; case CE: UNREORIGIN( segPtr->u.c.center, drawData.center, xx->angle, xx->orig ); break; case RA: segPtr->u.c.radius = drawData.radius; break; case A1: segPtr->u.c.a0 = NormalizeAngle( drawData.angle0-xx->angle ); drawData.angle1 = NormalizeAngle( drawData.angle0+drawData.angle ); drawDesc[A2].mode |= DESC_CHANGE; break; case A2: segPtr->u.c.a0 = NormalizeAngle( drawData.angle1-segPtr->u.c.a1-xx->angle ); drawData.angle0 = NormalizeAngle( segPtr->u.c.a0+xx->angle ); drawDesc[A1].mode |= DESC_CHANGE; break; case BE: BenchUpdateOrientationList( (long)wListGetItemContext((wList_p)drawDesc[BE].control0, drawData.benchChoice ), (wList_p)drawDesc[OR].control0 ); if ( drawData.benchOrient < wListGetCount( (wList_p)drawDesc[OR].control0 ) ) wListSetIndex( (wList_p)drawDesc[OR].control0, drawData.benchOrient ); else drawData.benchOrient = 0; segPtr->u.l.option = GetBenchData( (long)wListGetItemContext((wList_p)drawDesc[BE].control0, drawData.benchChoice ), drawData.benchOrient ); break; case OR: segPtr->u.l.option = GetBenchData( (long)wListGetItemContext((wList_p)drawDesc[BE].control0, drawData.benchChoice ), drawData.benchOrient ); break; case DS: segPtr->u.l.option = drawData.dimenSize; break; case TP: UNREORIGIN( segPtr->u.t.pos, drawData.endPt[0], xx->angle, xx->orig ); break; case TA: //segPtr->u.t.angle = NormalizeAngle( drawData.angle ); xx->angle = NormalizeAngle( drawData.angle ); break; case TS: fontSize = (long)segPtr->u.t.fontSize; UpdateFontSizeList( &fontSize, (wList_p)drawDesc[TS].control0, drawData.fontSizeInx ); segPtr->u.t.fontSize = fontSize; break; case TX: if ( wTextGetModified((wText_p)drawDesc[TX].control0 )) { int len = wTextGetSize((wText_p)drawDesc[TX].control0); MyFree( segPtr->u.t.string ); segPtr->u.t.string = (char *)MyMalloc(len+1); wTextGetText((wText_p)drawDesc[TX].control0, segPtr->u.t.string, len+1); segPtr->u.t.string[len] = '\0'; //Make sure of null term } break; case LY: SetTrkLayer( trk, drawData.layer); break; default: AbortProg( "bad op" ); } ComputeDrawBoundingBox( trk ); DrawNewTrack( trk ); DoCurCommand( C_REDRAW, zero ); } static void DescribeDraw( track_p trk, char * str, CSIZE_T len ) { struct extraData *xx = GetTrkExtraData(trk); coOrd pos = oldMarker; trkSeg_p segPtr; int inx; char * title = NULL; char * polyType = NULL; DistanceSegs( xx->orig, xx->angle, xx->segCnt, xx->segs, &pos, &drawSegInx ); if ( drawSegInx==-1 ) return; segPtr = &xx->segs[drawSegInx]; for ( inx=0; inxcolor; drawData.layer = GetTrkLayer(trk); drawDesc[CO].mode = 0; drawData.lineWidth = (long)floor(segPtr->width*mainD.dpi+0.5); drawDesc[LW].mode = 0; drawDesc[LY].mode = DESC_NOREDRAW; drawDesc[BE].mode = drawDesc[OR].mode = drawDesc[DS].mode = DESC_IGNORE; drawData.pivot = DESC_PIVOT_MID; switch ( segPtr->type ) { case SEG_STRLIN: case SEG_DIMLIN: case SEG_BENCH: case SEG_TBLEDGE: REORIGIN( drawData.endPt[0], segPtr->u.l.pos[0], xx->angle, xx->orig ); REORIGIN( drawData.endPt[1], segPtr->u.l.pos[1], xx->angle, xx->orig ); drawData.length = FindDistance( drawData.endPt[0], drawData.endPt[1] ); drawData.angle = FindAngle( drawData.endPt[0], drawData.endPt[1] ); drawDesc[LN].mode = drawDesc[AL].mode = drawDesc[PV].mode = 0; drawDesc[E0].mode = drawDesc[E1].mode = 0; switch (segPtr->type) { case SEG_STRLIN: title = _("Straight Line"); break; case SEG_DIMLIN: title = _("Dimension Line"); drawDesc[CO].mode = DESC_IGNORE; drawDesc[LW].mode = DESC_IGNORE; drawData.dimenSize = (wIndex_t)segPtr->u.l.option; drawDesc[DS].mode = 0; break; case SEG_BENCH: title = _("Lumber"); drawDesc[LW].mode = DESC_IGNORE; drawDesc[BE].mode = drawDesc[OR].mode = 0; drawData.benchChoice = GetBenchListIndex( segPtr->u.l.option ); drawData.benchOrient = (wIndex_t)(segPtr->u.l.option&0xFF); break; case SEG_TBLEDGE: title = _("Table Edge"); drawDesc[CO].mode = DESC_IGNORE; drawDesc[LW].mode = DESC_IGNORE; break; } break; case SEG_CRVLIN: REORIGIN( drawData.center, segPtr->u.c.center, xx->angle, xx->orig ); drawData.radius = fabs(segPtr->u.c.radius); drawDesc[CE].mode = drawDesc[RA].mode = 0; if ( segPtr->u.c.a1 >= 360.0 ) { title = _("Circle"); } else { drawData.angle = segPtr->u.c.a1; drawData.angle0 = NormalizeAngle( segPtr->u.c.a0+xx->angle ); drawData.angle1 = NormalizeAngle( drawData.angle0+drawData.angle ); drawDesc[AL].mode = drawDesc[A1].mode = drawDesc[A2].mode = 0; title = _("Curved Line"); } break; case SEG_FILCRCL: REORIGIN( drawData.center, segPtr->u.c.center, xx->angle, xx->orig ); drawData.radius = fabs(segPtr->u.c.radius); drawDesc[CE].mode = drawDesc[RA].mode = 0; drawDesc[LW].mode = DESC_IGNORE; title = _("Filled Circle"); break; case SEG_POLY: drawData.pointCount = segPtr->u.p.cnt; drawDesc[VC].mode = DESC_RO; drawDesc[PT].mode = DESC_RO; switch (segPtr->u.p.polyType) { case RECTANGLE: polyType = _("Rectangle"); break; default: polyType = _("Freeform"); } strncpy( drawData.polyType, polyType, sizeof drawData.polyType ); title = _("Polygonal Line"); break; case SEG_FILPOLY: drawData.pointCount = segPtr->u.p.cnt; drawDesc[VC].mode = DESC_RO; drawDesc[LW].mode = DESC_IGNORE; drawDesc[PT].mode = DESC_RO; switch (segPtr->u.p.polyType) { case RECTANGLE: polyType =_("Rectangle"); break; default: polyType = _("Freeform"); } strncpy( drawData.polyType, polyType, sizeof drawData.polyType ); title = _("Polygon"); break; case SEG_TEXT: REORIGIN( drawData.endPt[0], segPtr->u.t.pos, xx->angle, xx->orig ); drawData.angle = NormalizeAngle( xx->angle ); strncpy( drawData.text, segPtr->u.t.string, sizeof drawData.text ); drawData.text[sizeof drawData.text-1] ='\0'; drawDesc[TP].mode = drawDesc[TS].mode = drawDesc[TX].mode = drawDesc[TA].mode = drawDesc[CO].mode = 0; /*Allow Text color setting*/ drawDesc[LW].mode = DESC_IGNORE; title = _("Text"); break; default: AbortProg( "bad seg type" ); } sprintf( str, _("%s: Layer=%d"), title, GetTrkLayer(trk)+1 ); DoDescribe( title, trk, drawDesc, UpdateDraw ); if ( segPtr->type==SEG_BENCH && drawDesc[BE].control0!=NULL && drawDesc[OR].control0!=NULL) { BenchLoadLists( (wList_p)drawDesc[BE].control0, (wList_p)drawDesc[OR].control0 ); wListSetIndex( (wList_p)drawDesc[BE].control0, drawData.benchChoice ); BenchUpdateOrientationList( (long)wListGetItemContext((wList_p)drawDesc[BE].control0, drawData.benchChoice ), (wList_p)drawDesc[OR].control0 ); wListSetIndex( (wList_p)drawDesc[OR].control0, drawData.benchOrient ); } if ( segPtr->type==SEG_DIMLIN && drawDesc[DS].control0!=NULL ) { wListClear( (wList_p)drawDesc[DS].control0 ); wListAddValue( (wList_p)drawDesc[DS].control0, _("Tiny"), NULL, (void*)0 ); wListAddValue( (wList_p)drawDesc[DS].control0, _("Small"), NULL, (void*)1 ); wListAddValue( (wList_p)drawDesc[DS].control0, _("Medium"), NULL, (void*)2 ); wListAddValue( (wList_p)drawDesc[DS].control0, _("Large"), NULL, (void*)3 ); wListSetIndex( (wList_p)drawDesc[DS].control0, drawData.dimenSize ); } if ( segPtr->type==SEG_TEXT && drawDesc[TS].control0!=NULL ) { LoadFontSizeList( (wList_p)drawDesc[TS].control0, (long)segPtr->u.t.fontSize ); } } static void DrawDraw( track_p t, drawCmd_p d, wDrawColor color ) { struct extraData * xx = GetTrkExtraData(t); if ( (d->funcs->options&DC_QUICK) == 0 ) DrawSegs( d, xx->orig, xx->angle, xx->segs, xx->segCnt, 0.0, color ); } static void DeleteDraw( track_p t ) { /* Get rid of points if specified */ struct extraData * xx = GetTrkExtraData(t); if (xx->segs[0].type == SEG_POLY || xx->segs[0].type == SEG_FILPOLY) { MyFree(xx->segs[0].u.p.pts); } } static BOOL_T WriteDraw( track_p t, FILE * f ) { struct extraData * xx = GetTrkExtraData(t); BOOL_T rc = TRUE; rc &= fprintf(f, "DRAW %d %d 0 0 0 %0.6f %0.6f 0 %0.6f\n", GetTrkIndex(t), GetTrkLayer(t), xx->orig.x, xx->orig.y, xx->angle )>0; rc &= WriteSegs( f, xx->segCnt, xx->segs ); return rc; } static void ReadDraw( char * header ) { track_p trk; wIndex_t index; coOrd orig; DIST_T elev; ANGLE_T angle; wIndex_t layer; struct extraData * xx; if ( !GetArgs( header+5, paramVersion<3?"dXpYf":paramVersion<9?"dL000pYf":"dL000pff", &index, &layer, &orig, &elev, &angle ) ) return; ReadSegs(); if (tempSegs_da.cnt == 1) { trk = MakeDrawFromSeg1( index, orig, angle, &tempSegs(0) ); SetTrkLayer( trk, layer ); } else { trk = NewTrack( index, T_DRAW, 0, sizeof *xx + (tempSegs_da.cnt-1) * sizeof *(trkSeg_p)0 ); SetTrkLayer( trk, layer ); xx = GetTrkExtraData(trk); xx->orig = orig; xx->angle = angle; xx->segCnt = tempSegs_da.cnt; memcpy( xx->segs, tempSegs_da.ptr, tempSegs_da.cnt * sizeof *(trkSeg_p)0 ); ComputeDrawBoundingBox( trk ); } } static void MoveDraw( track_p trk, coOrd orig ) { struct extraData * xx = GetTrkExtraData(trk); xx->orig.x += orig.x; xx->orig.y += orig.y; ComputeDrawBoundingBox( trk ); } static void RotateDraw( track_p trk, coOrd orig, ANGLE_T angle ) { struct extraData * xx = GetTrkExtraData(trk); Rotate( &xx->orig, orig, angle ); xx->angle = NormalizeAngle( xx->angle + angle ); ComputeDrawBoundingBox( trk ); } static void RescaleDraw( track_p trk, FLOAT_T ratio ) { struct extraData * xx = GetTrkExtraData(trk); xx->orig.x *= ratio; xx->orig.y *= ratio; RescaleSegs( xx->segCnt, xx->segs, ratio, ratio, ratio ); } static STATUS_T ModifyDraw( track_p trk, wAction_t action, coOrd pos ) { struct extraData * xx = GetTrkExtraData(trk); STATUS_T rc; if (action == C_DOWN) { //UndrawNewTrack( trk ); } if ( action == C_MOVE ) ignoredDraw = trk; rc = DrawGeomModify( xx->orig, xx->angle, xx->segCnt, xx->segs, action, pos, GetTrkSelected(trk) ); ignoredDraw = NULL; if (action == C_UP) { ComputeDrawBoundingBox( trk ); DrawNewTrack( trk ); } return rc; } static void UngroupDraw( track_p trk ) { struct extraData * xx = GetTrkExtraData(trk); int inx; if ( xx->segCnt <= 1 ) return; DeleteTrack( trk, FALSE ); for ( inx=0; inxsegCnt; inx++ ) { trk = MakeDrawFromSeg( xx->orig, xx->angle, &xx->segs[inx] ); if ( trk ) { SetTrkBits( trk, TB_SELECTED ); DrawNewTrack( trk ); } } } static ANGLE_T GetAngleDraw( track_p trk, coOrd pos, EPINX_T * ep0, EPINX_T * ep1 ) { struct extraData * xx = GetTrkExtraData(trk); ANGLE_T angle; pos.x -= xx->orig.x; pos.y -= xx->orig.y; Rotate( &pos, zero, -xx->angle ); angle = GetAngleSegs( xx->segCnt, xx->segs, &pos, NULL, NULL, NULL, NULL, NULL); if ( ep0 ) *ep0 = -1; if ( ep1 ) *ep1 = -1; return NormalizeAngle( angle + xx->angle ); } static BOOL_T EnumerateDraw( track_p trk ) { struct extraData * xx; int inx; trkSeg_p segPtr; if ( trk ) { xx = GetTrkExtraData(trk); if ( xx->segCnt < 1 ) return TRUE; for ( inx=0; inxsegCnt; inx++ ) { segPtr = &xx->segs[inx]; if ( segPtr->type == SEG_BENCH ) { CountBench( segPtr->u.l.option, FindDistance( segPtr->u.l.pos[0], segPtr->u.l.pos[1] ) ); } } } else { TotalBench(); } return TRUE; } static void FlipDraw( track_p trk, coOrd orig, ANGLE_T angle ) { struct extraData * xx = GetTrkExtraData(trk); FlipPoint( &xx->orig, orig, angle ); xx->angle = NormalizeAngle( 2*angle - xx->angle + 180.0 ); FlipSegs( xx->segCnt, xx->segs, zero, angle ); ComputeDrawBoundingBox( trk ); } static BOOL_T StoreDraw( track_p trk, void **data, long * len) { struct extraData * xx = GetTrkExtraData(trk); if (xx->segs[0].type == SEG_POLY || xx->segs[0].type == SEG_FILPOLY) { *data = xx->segs[0].u.p.pts; *len = xx->segs[0].u.p.cnt* sizeof (coOrd); return TRUE; } return FALSE; } static BOOL_T ReplayDraw( track_p trk, void * data, long len) { struct extraData * xx = GetTrkExtraData(trk); if (xx->segs[0].type == SEG_POLY || xx->segs[0].type == SEG_FILPOLY) { xx->segs[0].u.p.pts = MyMalloc(len); memcpy(xx->segs[0].u.p.pts,data,len); return TRUE; } return FALSE; } static trackCmd_t drawCmds = { "DRAW", DrawDraw, DistanceDraw, DescribeDraw, DeleteDraw, WriteDraw, ReadDraw, MoveDraw, RotateDraw, RescaleDraw, NULL, GetAngleDraw, /* getAngle */ NULL, /* split */ NULL, /* traverse */ EnumerateDraw, NULL, /* redraw */ NULL, /* trim */ NULL, /* merge */ ModifyDraw, NULL, /* getLength */ NULL, /* getTrackParams */ NULL, /* moveEndPt */ NULL, /* query */ UngroupDraw, FlipDraw, NULL, NULL, NULL, NULL, /*Parallel*/ NULL, NULL, /*MakeSegs*/ ReplayDraw, StoreDraw }; EXPORT BOOL_T OnTableEdgeEndPt( track_p trk, coOrd * pos ) { track_p trk1; struct extraData *xx; coOrd pos1 = *pos; ignoredTableEdge = trk; if ((trk1 = OnTrack( &pos1, FALSE, FALSE )) != NULL && GetTrkType(trk1) == T_DRAW) { ignoredTableEdge = NULL; xx = GetTrkExtraData(trk1); if (xx->segCnt < 1) return FALSE; if (xx->segs[0].type == SEG_TBLEDGE) { if ( IsClose( FindDistance( *pos, xx->segs[0].u.l.pos[0] ) ) ) { *pos = xx->segs[0].u.l.pos[0]; return TRUE; } else if ( IsClose( FindDistance( *pos, xx->segs[0].u.l.pos[1] ) ) ) { *pos = xx->segs[0].u.l.pos[1]; return TRUE; } } } ignoredTableEdge = NULL; return FALSE; } EXPORT BOOL_T GetClosestEndPt( track_p trk, coOrd * pos) { struct extraData *xx; if (GetTrkType(trk) == T_DRAW) { ignoredTableEdge = NULL; xx = GetTrkExtraData(trk); if (xx->segCnt < 1) return FALSE; DIST_T dd0,dd1; coOrd p00,p0,p1; p00 = *pos; if (GetTrkType(trk) == T_DRAW) { Rotate(&p00,xx->orig,-xx->angle); p00.x -= xx->orig.x; p00.y -= xx->orig.y; switch (xx->segs[0].type) { case SEG_CRVLIN: PointOnCircle( &p0, xx->segs[0].u.c.center, fabs(xx->segs[0].u.c.radius), xx->segs[0].u.c.a0 ); dd0 = FindDistance( p00, p0); PointOnCircle( &p1, xx->segs[0].u.c.center, fabs(xx->segs[0].u.c.radius), xx->segs[0].u.c.a0 + xx->segs[0].u.c.a1); dd1 = FindDistance( p00, p1); break; case SEG_STRLIN: dd0 = FindDistance( p00, xx->segs[0].u.l.pos[0]); p0 = xx->segs[0].u.l.pos[0]; dd1 = FindDistance( p00, xx->segs[0].u.l.pos[1]); p1 = xx->segs[0].u.l.pos[1]; break; case SEG_BEZLIN: dd0 = FindDistance( p00, xx->segs[0].u.b.pos[0]); p0 = xx->segs[0].u.b.pos[0]; dd1 = FindDistance( p00, xx->segs[0].u.b.pos[3]); p1 = xx->segs[0].u.b.pos[3]; break; default: return FALSE; } p0.x += xx->orig.x; p0.y += xx->orig.y; Rotate(&p0,xx->orig,xx->angle); p1.x += xx->orig.x; p1.y += xx->orig.y; Rotate(&p1,xx->orig,xx->angle); } else if (GetTrkType(trk) == T_BZRLIN) { coOrd p0,p1; xx = GetTrkExtraData(trk); p0 = xx->segs[0].u.b.pos[0]; p1 = xx->segs[0].u.b.pos[3]; dd0 = FindDistance(p00,p0); dd1 = FindDistance(p00,p1); } else return FALSE; if (dd0>dd1) { * pos = p1; return TRUE; } else { * pos = p0; return TRUE; } } return FALSE; } static void DrawRedraw(void); static drawContext_t drawCmdContext = { InfoMessage, DrawRedraw, &mainD, OP_LINE }; static void DrawRedraw( void ) { MainRedraw(); MapRedraw(); } static wIndex_t benchChoice; static wIndex_t benchOrient; static wIndex_t dimArrowSize; wDrawColor lineColor = 1; long lineWidth = 0; static wDrawColor benchColor; static paramIntegerRange_t i0_100 = { 0, 100, 25 }; static paramData_t drawPLs[] = { #define drawWidthPD (drawPLs[0]) { PD_LONG, &drawCmdContext.Width, "linewidth", PDO_NORECORD, &i0_100, N_("Line Width") }, #define drawColorPD (drawPLs[1]) { PD_COLORLIST, &lineColor, "linecolor", PDO_NORECORD, NULL, N_("Color") }, #define drawBenchColorPD (drawPLs[2]) { PD_COLORLIST, &benchColor, "benchcolor", PDO_NORECORD, NULL, N_("Color") }, #define drawBenchChoicePD (drawPLs[3]) #ifdef WINDOWS { PD_DROPLIST, &benchChoice, "benchlist", PDO_NOPREF|PDO_NORECORD|PDO_LISTINDEX, (void*)120, N_("Lumber Type") }, #else { PD_DROPLIST, &benchChoice, "benchlist", PDO_NOPREF|PDO_NORECORD|PDO_LISTINDEX, (void*)145, N_("Lumber Type") }, #endif #define drawBenchOrientPD (drawPLs[4]) #ifdef WINDOWS { PD_DROPLIST, &benchOrient, "benchorient", PDO_NOPREF|PDO_NORECORD|PDO_LISTINDEX, (void*)45, "", 0 }, #else { PD_DROPLIST, &benchOrient, "benchorient", PDO_NOPREF|PDO_NORECORD|PDO_LISTINDEX, (void*)105, "", 0 }, #endif #define drawDimArrowSizePD (drawPLs[5]) { PD_DROPLIST, &dimArrowSize, "arrowsize", PDO_NORECORD|PDO_LISTINDEX, (void*)80, N_("Size") } }; static paramGroup_t drawPG = { "draw", 0, drawPLs, sizeof drawPLs/sizeof drawPLs[0] }; static char * objectName[] = { N_("Straight"), N_("Dimension"), N_("Lumber"), N_("Table Edge"), N_("Curved"), N_("Curved"), N_("Curved"), N_("Curved"), N_("Circle"), N_("Circle"), N_("Circle"), N_("Box"), N_("Polyline"), N_("Filled Circle"), N_("Filled Circle"), N_("Filled Circle"), N_("Filled Box"), N_("Polygon"), N_("Bezier Line"), NULL}; static STATUS_T CmdDraw( wAction_t action, coOrd pos ) { static BOOL_T infoSubst = FALSE; wControl_p controls[4]; char * labels[3]; static char labelName[40]; wAction_t act2 = (action&0xFF) | (bezCmdCreateLine<<8); switch (action&0xFF) { case C_START: ParamLoadControls( &drawPG ); /*drawContext = &drawCmdContext;*/ drawWidthPD.option |= PDO_NORECORD; drawColorPD.option |= PDO_NORECORD; drawBenchColorPD.option |= PDO_NORECORD; drawBenchChoicePD.option |= PDO_NORECORD; drawBenchOrientPD.option |= PDO_NORECORD; drawDimArrowSizePD.option |= PDO_NORECORD; drawCmdContext.Op = (wIndex_t)(long)commandContext; if ( drawCmdContext.Op < 0 || drawCmdContext.Op > OP_LAST ) { NoticeMessage( "cmdDraw: Op %d", _("Ok"), NULL, drawCmdContext.Op ); drawCmdContext.Op = OP_LINE; } /*DrawGeomOp( (void*)(drawCmdContext.Op>=0?drawCmdContext.Op:OP_LINE) );*/ infoSubst = TRUE; switch( drawCmdContext.Op ) { case OP_LINE: case OP_CURVE1: case OP_CURVE2: case OP_CURVE3: case OP_CURVE4: case OP_CIRCLE2: case OP_CIRCLE3: case OP_BOX: case OP_POLY: case OP_BEZLIN: controls[0] = drawWidthPD.control; controls[1] = drawColorPD.control; controls[2] = NULL; sprintf( labelName, _("%s Line Width"), _(objectName[drawCmdContext.Op]) ); labels[0] = labelName; labels[1] = N_("Color"); InfoSubstituteControls( controls, labels ); drawWidthPD.option &= ~PDO_NORECORD; drawColorPD.option &= ~PDO_NORECORD; lineWidth = drawCmdContext.Width; break; case OP_FILLCIRCLE2: case OP_FILLCIRCLE3: case OP_FILLBOX: case OP_FILLPOLY: controls[0] = drawColorPD.control; controls[1] = NULL; sprintf( labelName, _("%s Color"), _(objectName[drawCmdContext.Op]) ); labels[0] = labelName; ParamLoadControls( &drawPG ); InfoSubstituteControls( controls, labels ); drawColorPD.option &= ~PDO_NORECORD; break; case OP_BENCH: controls[0] = drawBenchChoicePD.control; controls[1] = drawBenchOrientPD.control; controls[2] = drawBenchColorPD.control; controls[3] = NULL; labels[0] = N_("Lumber Type"); labels[1] = ""; labels[2] = N_("Color"); if ( wListGetCount( (wList_p)drawBenchChoicePD.control ) == 0 ) BenchLoadLists( (wList_p)drawBenchChoicePD.control, (wList_p)drawBenchOrientPD.control ); ParamLoadControls( &drawPG ); BenchUpdateOrientationList( (long)wListGetItemContext( (wList_p)drawBenchChoicePD.control, benchChoice ), (wList_p)drawBenchOrientPD.control ); wListSetIndex( (wList_p)drawBenchOrientPD.control, benchOrient ); InfoSubstituteControls( controls, labels ); drawBenchColorPD.option &= ~PDO_NORECORD; drawBenchChoicePD.option &= ~PDO_NORECORD; drawBenchOrientPD.option &= ~PDO_NORECORD; break; case OP_DIMLINE: controls[0] = drawDimArrowSizePD.control; controls[1] = NULL; labels[0] = N_("Dimension Line Size"); if ( wListGetCount( (wList_p)drawDimArrowSizePD.control ) == 0 ) { wListAddValue( (wList_p)drawDimArrowSizePD.control, _("Tiny"), NULL, NULL ); wListAddValue( (wList_p)drawDimArrowSizePD.control, _("Small"), NULL, NULL ); wListAddValue( (wList_p)drawDimArrowSizePD.control, _("Medium"), NULL, NULL ); wListAddValue( (wList_p)drawDimArrowSizePD.control, _("Large"), NULL, NULL ); } ParamLoadControls( &drawPG ); InfoSubstituteControls( controls, labels ); drawDimArrowSizePD.option &= ~PDO_NORECORD; break; case OP_TBLEDGE: InfoSubstituteControls( NULL, NULL ); InfoMessage( _("Drag to create Table Edge") ); drawColorPD.option &= ~PDO_NORECORD; break; default: InfoSubstituteControls( NULL, NULL ); infoSubst = FALSE; } ParamGroupRecord( &drawPG ); if (drawCmdContext.Op == OP_BEZLIN) return CmdBezCurve(act2, pos); DrawGeomMouse( C_START, pos, &drawCmdContext ); return C_CONTINUE; case wActionLDown: ParamLoadData( &drawPG ); if (drawCmdContext.Op == OP_BEZLIN) { act2 = action | (bezCmdCreateLine<<8); return CmdBezCurve(act2, pos); } if ( drawCmdContext.Op == OP_BENCH ) { drawCmdContext.benchOption = GetBenchData( (long)wListGetItemContext((wList_p)drawBenchChoicePD.control, benchChoice ), benchOrient ); drawCmdContext.Color = benchColor; } else if ( drawCmdContext.Op == OP_DIMLINE ) { drawCmdContext.benchOption = dimArrowSize; } else { drawCmdContext.Color = lineColor; } if ( infoSubst ) { InfoSubstituteControls( NULL, NULL ); infoSubst = FALSE; } case wActionLDrag: ParamLoadData( &drawPG ); case wActionMove: case wActionLUp: case wActionRDown: case wActionRDrag: case wActionRUp: case wActionText: case C_CMDMENU: if (drawCmdContext.Op == OP_BEZLIN) return CmdBezCurve(act2, pos); if (!((MyGetKeyState() & WKEY_SHIFT) != 0)) { SnapPos( &pos ); } return DrawGeomMouse( action, pos, &drawCmdContext ); case C_CANCEL: InfoSubstituteControls( NULL, NULL ); if (drawCmdContext.Op == OP_BEZLIN) return CmdBezCurve(act2, pos); return DrawGeomMouse( action, pos, &drawCmdContext ); case C_OK: if (drawCmdContext.Op == OP_BEZLIN) return CmdBezCurve(act2, pos); return DrawGeomMouse( (0x0D<<8|wActionText), pos, &drawCmdContext ); /*DrawOk( NULL );*/ case C_FINISH: if (drawCmdContext.Op == OP_BEZLIN) return CmdBezCurve(act2, pos); return DrawGeomMouse( (0x0D<<8|wActionText), pos, &drawCmdContext ); /*DrawOk( NULL );*/ case C_REDRAW: if (drawCmdContext.Op == OP_BEZLIN) return CmdBezCurve(act2, pos); return DrawGeomMouse( action, pos, &drawCmdContext ); default: return C_CONTINUE; } } #include "bitmaps/dline.xpm" #include "bitmaps/ddimlin.xpm" #include "bitmaps/dbench.xpm" #include "bitmaps/dtbledge.xpm" #include "bitmaps/dcurve1.xpm" #include "bitmaps/dcurve2.xpm" #include "bitmaps/dcurve3.xpm" #include "bitmaps/dcurve4.xpm" /*#include "bitmaps/dcircle1.xpm"*/ #include "bitmaps/dcircle2.xpm" #include "bitmaps/dcircle3.xpm" /*#include "bitmaps/dflcrcl1.xpm"*/ #include "bitmaps/dflcrcl2.xpm" #include "bitmaps/dflcrcl3.xpm" #include "bitmaps/dbox.xpm" #include "bitmaps/dfilbox.xpm" #include "bitmaps/dpoly.xpm" #include "bitmaps/dfilpoly.xpm" #include "bitmaps/dbezier.xpm" typedef struct { char **xpm; int OP; char * shortName; char * cmdName; char * helpKey; long acclKey; } drawData_t; static drawData_t dlineCmds[] = { { dline_xpm, OP_LINE, N_("Line"), N_("Draw Line"), "cmdDrawLine", ACCL_DRAWLINE }, { ddimlin_xpm, OP_DIMLINE, N_("Dimension Line"), N_("Draw Dimension Line"), "cmdDrawDimLine", ACCL_DRAWDIMLINE }, { dbench_xpm, OP_BENCH, N_("Benchwork"), N_("Draw Benchwork"), "cmdDrawBench", ACCL_DRAWBENCH }, { dtbledge_xpm, OP_TBLEDGE, N_("Table Edge"), N_("Draw Table Edge"), "cmdDrawTableEdge", ACCL_DRAWTBLEDGE } }; static drawData_t dcurveCmds[] = { { dcurve1_xpm, OP_CURVE1, N_("Curve End"), N_("Draw Curve from End"), "cmdDrawCurveEndPt", ACCL_DRAWCURVE1 }, { dcurve2_xpm, OP_CURVE2, N_("Curve Tangent"), N_("Draw Curve from Tangent"), "cmdDrawCurveTangent", ACCL_DRAWCURVE2 }, { dcurve3_xpm, OP_CURVE3, N_("Curve Center"), N_("Draw Curve from Center"), "cmdDrawCurveCenter", ACCL_DRAWCURVE3 }, { dcurve4_xpm, OP_CURVE4, N_("Curve Chord"), N_("Draw Curve from Chord"), "cmdDrawCurveChord", ACCL_DRAWCURVE4 }, { dbezier_xpm, OP_BEZLIN, N_("Bezier Curve"), N_("Draw Bezier"), "cmdDrawBezierCurve", ACCL_DRAWBEZLINE } }; static drawData_t dcircleCmds[] = { /*{ dcircle1_xpm, OP_CIRCLE1, "Circle Fixed Radius", "Draw Fixed Radius Circle", "cmdDrawCircleFixedRadius", ACCL_DRAWCIRCLE1 },*/ { dcircle2_xpm, OP_CIRCLE3, N_("Circle Tangent"), N_("Draw Circle from Tangent"), "cmdDrawCircleTangent", ACCL_DRAWCIRCLE2 }, { dcircle3_xpm, OP_CIRCLE2, N_("Circle Center"), N_("Draw Circle from Center"), "cmdDrawCircleCenter", ACCL_DRAWCIRCLE3 }, /*{ dflcrcl1_xpm, OP_FILLCIRCLE1, "Circle Filled Fixed Radius", "Draw Fixed Radius Filled Circle", "cmdDrawFilledCircleFixedRadius", ACCL_DRAWFILLCIRCLE1 },*/ { dflcrcl2_xpm, OP_FILLCIRCLE3, N_("Circle Filled Tangent"), N_("Draw Filled Circle from Tangent"), "cmdDrawFilledCircleTangent", ACCL_DRAWFILLCIRCLE2 }, { dflcrcl3_xpm, OP_FILLCIRCLE2, N_("Circle Filled Center"), N_("Draw Filled Circle from Center"), "cmdDrawFilledCircleCenter", ACCL_DRAWFILLCIRCLE3 } }; static drawData_t dshapeCmds[] = { { dbox_xpm, OP_BOX, N_("Box"), N_("Draw Box"), "cmdDrawBox", ACCL_DRAWBOX }, { dfilbox_xpm, OP_FILLBOX, N_("Filled Box"), N_("Draw Filled Box"), "cmdDrawFilledBox", ACCL_DRAWFILLBOX }, { dpoly_xpm, OP_POLY, N_("Poly Line"), N_("Draw Polyline"), "cmdDrawPolyline", ACCL_DRAWPOLYLINE }, { dfilpoly_xpm, OP_FILLPOLY, N_("Polygon"), N_("Draw Polygon"), "cmdDrawPolygon", ACCL_DRAWPOLYGON } }; typedef struct { char * helpKey; char * menuTitle; char * stickyLabel; int cnt; drawData_t * data; long acclKey; wIndex_t cmdInx; int curr; } drawStuff_t; static drawStuff_t drawStuff[4]; static drawStuff_t drawStuff[4] = { { "cmdDrawLineSetCmd", N_("Straight Objects"), N_("Draw Straight Objects"), 4, dlineCmds }, { "cmdDrawCurveSetCmd", N_("Curved Lines"), N_("Draw Curved Lines"), 5, dcurveCmds }, { "cmdDrawCircleSetCmd", N_("Circle Lines"), N_("Draw Circles"), 4, dcircleCmds }, { "cmdDrawShapeSetCmd", N_("Shapes"), N_("Draw Shapes"), 4, dshapeCmds} }; static void ChangeDraw( long changes ) { wIndex_t choice, orient; if ( changes & CHANGE_UNITS ) { if ( drawBenchChoicePD.control && drawBenchOrientPD.control ) { choice = wListGetIndex( (wList_p)drawBenchChoicePD.control ); orient = wListGetIndex( (wList_p)drawBenchOrientPD.control ); BenchLoadLists( (wList_p)drawBenchChoicePD.control, (wList_p)drawBenchOrientPD.control ); wListSetIndex( (wList_p)drawBenchChoicePD.control, choice ); wListSetIndex( (wList_p)drawBenchOrientPD.control, orient ); } } } static void DrawDlgUpdate( paramGroup_p pg, int inx, void * valueP ) { if (drawCmdContext.Op == OP_BEZLIN) { if ( (inx == 0 && pg->paramPtr[inx].valueP == &drawCmdContext.Width) || (inx == 1 && pg->paramPtr[inx].valueP == &lineColor)) { lineWidth = drawCmdContext.Width; UpdateParms(lineColor, lineWidth); } } if ( inx >= 0 && pg->paramPtr[inx].valueP == &benchChoice ) BenchUpdateOrientationList( (long)wListGetItemContext( (wList_p)drawBenchChoicePD.control, (wIndex_t)*(long*)valueP ), (wList_p)drawBenchOrientPD.control ); } EXPORT void InitCmdDraw( wMenu_p menu ) { int inx1, inx2; drawStuff_t * dsp; drawData_t * ddp; wIcon_p icon; drawCmdContext.Color = wDrawColorBlack; lineColor = wDrawColorBlack; benchColor = wDrawFindColor( wRGB(255,192,0) ); ParamCreateControls( &drawPG, DrawDlgUpdate ); for ( inx1=0; inx1<4; inx1++ ) { dsp = &drawStuff[inx1]; ButtonGroupBegin( _(dsp->menuTitle), dsp->helpKey, _(dsp->stickyLabel) ); for ( inx2=0; inx2cnt; inx2++ ) { ddp = &dsp->data[inx2]; icon = wIconCreatePixMap( ddp->xpm ); AddMenuButton( menu, CmdDraw, ddp->helpKey, _(ddp->cmdName), icon, LEVEL0_50, IC_STICKY|IC_POPUP2, ddp->acclKey, (void *)(intptr_t)ddp->OP ); } ButtonGroupEnd(); } ParamRegister( &drawPG ); RegisterChangeNotification( ChangeDraw ); } BOOL_T ReadTableEdge( char * line ) { track_p trk; TRKINX_T index; DIST_T elev0, elev1; trkSeg_t seg; wIndex_t layer; if ( !GetArgs( line, paramVersion<3?"dXpYpY":paramVersion<9?"dL000pYpY":"dL000pfpf", &index, &layer, &seg.u.l.pos[0], &elev0, &seg.u.l.pos[1], &elev1 ) ) return FALSE; seg.type = SEG_TBLEDGE; seg.color = wDrawColorBlack; seg.width = 0; trk = MakeDrawFromSeg1( index, zero, 0.0, &seg ); SetTrkLayer(trk, layer); return TRUE; } /** * Create a new segment for text. The data are stored in a trk structure. * Storage for the string is dynamically allocated. * * \param index IN of new element * \param pos IN coordinates of element * \param angle IN orientation * \param text IN text itself * \param textSize IN font size in pts * \param color IN text color * \return the newly allocated trk structure */ EXPORT track_p NewText( wIndex_t index, coOrd pos, ANGLE_T angle, char * text, CSIZE_T textSize, wDrawColor color ) { trkSeg_t tempSeg; track_p trk; tempSeg.type = SEG_TEXT; tempSeg.color = color; tempSeg.width = 0; tempSeg.u.t.pos = zero; tempSeg.u.t.angle = angle; tempSeg.u.t.fontP = NULL; tempSeg.u.t.fontSize = textSize; tempSeg.u.t.string = MyStrdup( text ); trk = MakeDrawFromSeg1( index, pos, angle, &tempSeg ); return trk; } EXPORT BOOL_T ReadText( char * line ) { coOrd pos; CSIZE_T textSize; char * text; wIndex_t index; wIndex_t layer; track_p trk; ANGLE_T angle; wDrawColor color = wDrawColorBlack; if ( paramVersion<3 ) { if (!GetArgs( line, "XXpYql", &index, &layer, &pos, &angle, &text, &textSize )) return FALSE; } else if (paramVersion<9 ) { if (!GetArgs(line, "dL000pYql", &index, &layer, &pos, &angle, &text, &textSize)) return FALSE; } else { if (!GetArgs(line, "dLl00pfql", &index, &layer, &color, &pos, &angle, &text, &textSize )) return FALSE; } char * old = text; text = ConvertFromEscapedText(text); MyFree(old); trk = NewText( index, pos, angle, text, textSize, color ); SetTrkLayer( trk, layer ); MyFree(text); return TRUE; } EXPORT void InitTrkDraw( void ) { T_DRAW = InitObject( &drawCmds ); AddParam( "TABLEEDGE", ReadTableEdge ); AddParam( "TEXT", ReadText ); }