/* * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/bin/cnote.c,v 1.6 2008-03-10 18:59:53 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 "track.h" #include "i18n.h" /***************************************************************************** * * NOTE * */ static TRKTYP_T T_NOTE = -1; static wDrawBitMap_p note_bm; struct extraData { coOrd pos; char * text; }; extern BOOL_T inDescribeCmd; #define NOTEHIDE "CNOTE HIDE" #define NOTEDONE "CNOTE DONE" static char * mainText = NULL; static wWin_p noteW; static paramTextData_t noteTextData = { 300, 150 }; static paramData_t notePLs[] = { #define I_NOTETEXT (0) #define noteT ((wText_p)notePLs[I_NOTETEXT].control) { PD_TEXT, NULL, "text", PDO_DLGRESIZE, ¬eTextData } }; static paramGroup_t notePG = { "note", 0, notePLs, sizeof notePLs/sizeof notePLs[0] }; static track_p NewNote( wIndex_t index, coOrd p, long size ) { track_p t; struct extraData * xx; t = NewTrack( index, T_NOTE, 0, sizeof *xx ); xx = GetTrkExtraData(t); xx->pos = p; xx->text = (char*)MyMalloc( (int)size + 2 ); SetBoundingBox( t, p, p ); return t; } void ClearNote( void ) { if (mainText) { MyFree(mainText); mainText = NULL; } } static void NoteOk( void * junk ) { int len; if ( wTextGetModified(noteT) ) { ClearNote(); len = wTextGetSize( noteT ); mainText = (char*)MyMalloc( len+2 ); wTextGetText( noteT, mainText, len ); if (mainText[len-1] != '\n') { mainText[len++] = '\n'; } mainText[len] = '\0'; } wHide( noteW ); } void DoNote( void ) { if ( noteW == NULL ) { noteW = ParamCreateDialog( ¬ePG, MakeWindowTitle(_("Note")), _("Ok"), NoteOk, NULL, FALSE, NULL, F_RESIZE, NULL ); } wTextClear( noteT ); wTextAppend( noteT, mainText?mainText:_("Replace this text with your layout notes") ); wTextSetReadonly( noteT, FALSE ); wShow( noteW ); } /***************************************************************************** * NOTE OBJECT */ static void DrawNote( track_p t, drawCmd_p d, wDrawColor color ) { struct extraData *xx = GetTrkExtraData(t); coOrd p[4]; DIST_T dist; if (d->scale >= 16) return; if ( (d->funcs->options & wDrawOptTemp) == 0 ) { DrawBitMap( d, xx->pos, note_bm, color ); } else { dist = 0.1*d->scale; p[0].x = p[1].x = xx->pos.x-dist; p[2].x = p[3].x = xx->pos.x+dist; p[1].y = p[2].y = xx->pos.y-dist; p[3].y = p[0].y = xx->pos.y+dist; DrawLine( d, p[0], p[1], 0, color ); DrawLine( d, p[1], p[2], 0, color ); DrawLine( d, p[2], p[3], 0, color ); DrawLine( d, p[3], p[0], 0, color ); } } static DIST_T DistanceNote( track_p t, coOrd * p ) { struct extraData *xx = GetTrkExtraData(t); DIST_T d; d = FindDistance( *p, xx->pos ); if (d < 1.0) return d; return 100000.0; } static struct { coOrd pos; } noteData; typedef enum { OR, LY, TX } noteDesc_e; static descData_t noteDesc[] = { /*OR*/ { DESC_POS, N_("Position"), ¬eData.pos }, /*LY*/ { DESC_LAYER, N_("Layer"), NULL }, /*TX*/ { DESC_TEXT, NULL, NULL }, { DESC_NULL } }; static void UpdateNote( track_p trk, int inx, descData_p descUpd, BOOL_T needUndoStart ) { struct extraData *xx = GetTrkExtraData(trk); int len; switch ( inx ) { case OR: UndrawNewTrack( trk ); xx->pos = noteData.pos; SetBoundingBox( trk, xx->pos, xx->pos ); DrawNewTrack( trk ); break; case -1: if ( wTextGetModified((wText_p)noteDesc[TX].control0) ) { if ( needUndoStart ) UndoStart( _("Change Track"), "Change Track" ); UndoModify( trk ); MyFree( xx->text ); len = wTextGetSize( (wText_p)noteDesc[TX].control0 ); xx->text = (char*)MyMalloc( len+2 ); wTextGetText( (wText_p)noteDesc[TX].control0, xx->text, len ); if (xx->text[len-1] != '\n') { xx->text[len++] = '\n'; } xx->text[len] = '\0'; } break; default: break; } } static void DescribeNote( track_p trk, char * str, CSIZE_T len ) { struct extraData * xx = GetTrkExtraData(trk); strcpy( str, _("Note: ") ); len -= strlen(_("Note: ")); str += strlen(_("Note: ")); strncpy( str, xx->text, len ); for (;*str;str++) { if (*str=='\n') *str = ' '; } noteData.pos = xx->pos; noteDesc[TX].valueP = xx->text; noteDesc[OR].mode = 0; noteDesc[TX].mode = 0; noteDesc[LY].mode = DESC_RO; DoDescribe( _("Note"), trk, noteDesc, UpdateNote ); } static void DeleteNote( track_p t ) { struct extraData *xx = GetTrkExtraData(t); if (xx->text) MyFree( xx->text ); } static BOOL_T WriteNote( track_p t, FILE * f ) { struct extraData *xx = GetTrkExtraData(t); int len; BOOL_T addNL = FALSE; BOOL_T rc = TRUE; len = strlen(xx->text); if ( xx->text[len-1] != '\n' ) { len++; addNL = TRUE; } rc &= fprintf(f, "NOTE %d %d 0 0 %0.6f %0.6f 0 %d\n", GetTrkIndex(t), GetTrkLayer(t), xx->pos.x, xx->pos.y, len )>0; rc &= fprintf(f, "%s%s", xx->text, addNL?"\n":"" )>0; rc &= fprintf(f, " END\n")>0; return rc; } static void ReadNote( char * line ) { coOrd pos; DIST_T elev; CSIZE_T size; char * cp; track_p t; struct extraData *xx; int len; wIndex_t index; wIndex_t layer; int lineCount; if ( strncmp( line, "NOTE MAIN", 9 ) == 0 ){ if ( !GetArgs( line+9, paramVersion<3?"d":"0000d", &size ) ) return; if (mainText) MyFree( mainText ); mainText = (char*)MyMalloc( size+2 ); cp = mainText; } else { if ( !GetArgs( line+5, paramVersion<3?"XXpYd":paramVersion<9?"dL00pYd":"dL00pfd", &index, &layer, &pos, &elev, &size ) ) { return; } t = NewNote( index, pos, size+2 ); SetTrkLayer( t, layer ); xx = GetTrkExtraData(t); cp = xx->text; } lineCount = 0; while (1) { line = GetNextLine(); if (strncmp(line, " END", 7) == 0) break; len = strlen(line); if (size > 0 && size < len) { InputError( "NOTE text overflow", TRUE ); size = -1; } if (size > 0) { if ( lineCount != 0 ) { strcat( cp, "\n" ); cp++; size--; } strcpy( cp, line ); cp += len; size -= len; } lineCount++; } if (cp[-1] != '\n') *cp++ = '\n'; *cp = '\0'; } static void MoveNote( track_p trk, coOrd orig ) { struct extraData * xx = GetTrkExtraData( trk ); xx->pos.x += orig.x; xx->pos.y += orig.y; SetBoundingBox( trk, xx->pos, xx->pos ); } static void RotateNote( track_p trk, coOrd orig, ANGLE_T angle ) { struct extraData * xx = GetTrkExtraData( trk ); Rotate( &xx->pos, orig, angle ); SetBoundingBox( trk, xx->pos, xx->pos ); } static void RescaleNote( track_p trk, FLOAT_T ratio ) { struct extraData * xx = GetTrkExtraData( trk ); xx->pos.x *= ratio; xx->pos.y *= ratio; } static trackCmd_t noteCmds = { "NOTE", DrawNote, DistanceNote, DescribeNote, DeleteNote, WriteNote, ReadNote, MoveNote, RotateNote, RescaleNote, NULL, /* audit */ NULL, /* getAngle */ NULL, /* split */ NULL, /* traverse */ NULL, /* enumerate */ NULL /* redraw */ }; BOOL_T WriteMainNote( FILE* f ) { BOOL_T rc = TRUE; if (mainText && *mainText) { rc &= fprintf(f, "NOTE MAIN 0 0 0 0 %d\n", strlen(mainText) )>0; rc &= fprintf(f, "%s", mainText )>0; rc &= fprintf(f, " END\n")>0; } return rc; } /***************************************************************************** * NOTE COMMAND */ static STATUS_T CmdNote( wAction_t action, coOrd pos ) { static coOrd oldPos; track_p trk; struct extraData * xx; const char* tmpPtrText; switch (action) { case C_START: InfoMessage( _("Place a note on the layout") ); return C_CONTINUE; case C_DOWN: DrawBitMap( &tempD, pos, note_bm, normalColor ); oldPos = pos; return C_CONTINUE; case C_MOVE: DrawBitMap( &tempD, oldPos, note_bm, normalColor ); DrawBitMap( &tempD, pos, note_bm, normalColor ); oldPos = pos; return C_CONTINUE; break; case C_UP: UndoStart( _("New Note"), "New Note" ); trk = NewNote( -1, pos, 2 ); DrawNewTrack( trk ); xx = GetTrkExtraData(trk); tmpPtrText = _("Replace this text with your note"); xx->text = (char*)MyMalloc( strlen(tmpPtrText) + 1 ); strcpy( xx->text, tmpPtrText); inDescribeCmd = TRUE; DescribeNote( trk, message, sizeof message ); inDescribeCmd = FALSE; return C_CONTINUE; case C_REDRAW: DrawBitMap( &tempD, oldPos, note_bm, normalColor ); return C_CONTINUE; case C_CANCEL: DescribeCancel(); return C_CONTINUE; } return C_INFO; } #include "bitmaps/note.xbm" #include "bitmaps/cnote.xpm" void InitCmdNote( wMenu_p menu ) { ParamRegister( ¬ePG ); AddMenuButton( menu, CmdNote, "cmdNote", _("Note"), wIconCreatePixMap(cnote_xpm), LEVEL0_50, IC_POPUP2, ACCL_NOTE, NULL ); } void InitTrkNote( void ) { note_bm = wDrawBitMapCreate( mainD.d, note_width, note_width, 8, 8, note_bits ); T_NOTE = InitObject( ¬eCmds ); }