/** \file cnote.c * NOTE */ /* 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 "cundo.h" #include "custom.h" #include "fileio.h" #include "i18n.h" #include "param.h" #include "track.h" #include "utility.h" 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) { if (wTextGetModified(noteT)) { int len; 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]; if (d->scale >= 16) { return; } if ((d->funcs->options & wDrawOptTemp) == 0) { DrawBitMap(d, xx->pos, note_bm, color); } else { DIST_T dist; 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; unsigned int layer; } noteData; typedef enum { OR, LY, TX } noteDesc_e; static descData_t noteDesc[] = { /*OR*/ { DESC_POS, N_("Position"), ¬eData.pos }, /*LY*/ { DESC_LAYER, N_("Layer"), ¬eData.layer }, /*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); switch (inx) { case OR: xx->pos = noteData.pos; SetBoundingBox(trk, xx->pos, xx->pos); MainRedraw(); break; case LY: SetTrkLayer(trk, noteData.layer); MainRedraw(); break; case -1: if (wTextGetModified((wText_p)noteDesc[TX].control0)) { int len; 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'; } MainRedraw(); 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_NOREDRAW; 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; struct extraData *xx; 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 { track_p t; 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) { int len; 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 %lu\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; static int state_on = FALSE; switch (action) { case C_START: InfoMessage(_("Place a note on the layout")); return C_CONTINUE; case C_DOWN: state_on = TRUE; oldPos = pos; MainRedraw(); return C_CONTINUE; case C_MOVE: oldPos = pos; MainRedraw(); return C_CONTINUE; break; case C_UP: UndoStart(_("New Note"), "New Note"); state_on = FALSE; MainRedraw(); 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: if (state_on) 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); }