// Replace all of the symbols in our drawing with a different one... void CTinyCadDoc::ReplaceSymbol( hSYMBOL old_symbol, hSYMBOL new_symbol, bool keep_old_fields ) { // Search for methods, and look at their pins drawingIterator it = GetDrawingBegin(); while (it != GetDrawingEnd()) { CDrawingObject *ObjPtr = *it; if (ObjPtr->GetType() == xMethodEx3) { CDrawMethod *pMethod = static_cast<CDrawMethod*>(ObjPtr); pMethod->ReplaceSymbol( old_symbol, new_symbol, keep_old_fields ); pMethod->Display( TRUE ); } ++ it; } }
// Called after a paste or import to enable the // document to sort out the imported block when // necessary void CTinyCadDoc::UngroupSymbols() { // Scan and convert any imported symbols // into their component parts drawingIterator it = GetDrawingBegin(); while (it != GetDrawingEnd()) { drawingIterator current = it; ++ it; CDrawingObject *pObject = *current; // Is this a method object? if ( pObject->GetType() == xMethodEx3 && IsSelected(pObject)) { // Convert to the actual type CDrawMethod *pMethod = static_cast<CDrawMethod*>(pObject); // Get the symbol data CDPoint tr; drawingCollection method; pMethod->ExtractSymbol( tr,method ); // Remove the method from the linked list UnSelect(pMethod); Delete( pMethod ); // Now re-insert using the offset of the main // method CDPoint offset = method.front()->m_point_a; drawingIterator it = method.begin(); while (it != method.end()) { CDrawingObject *pInsertObject = *it; CDrawingObject *pDup = pInsertObject->Store(); pDup->m_point_a += offset; pDup->m_point_b += offset; Select( pDup ); ++ it; } } } }
// Remove an item from the drawing... void CTinyCadDoc::Delete( drawingIterator it) { CDrawingObject *pointer = *it; pointer->Display(); if (pointer == GetSelectable()) { SetSelectable( NULL ); } UnSelect(pointer); MarkDeleteForUndo( *it ); delete *it; m_drawing.erase( it ); SetModifiedFlag( TRUE ); }
// Set which part in the package to edit void CTinyCadSymbolDoc::EditPartInPackage( int p ) { int OldPart = GetPart(); // Get rid of any drawing tool SelectObject(new CDrawEditItem(this)); m_part = p; // Are there any pins selected for this part int innew = FALSE,inold = FALSE; drawingIterator it = GetDrawingBegin(); while (it != GetDrawingEnd()) { CDrawingObject *pointer = *it; if (pointer->GetType()==xPinEx && ((CDrawPin *)pointer)->GetPart()==GetPart()) innew = TRUE; if (pointer->GetType()==xPinEx && ((CDrawPin *)pointer)->GetPart()==OldPart) inold = TRUE; ++ it; } // Do we need to copy over the pins? if (!innew && inold && Message(IDS_COPYPINS,MB_YESNO | MB_ICONQUESTION)==IDYES) { CDrawPin *NewPin; drawingIterator it = GetDrawingBegin(); while (it != GetDrawingEnd()) { CDrawingObject *pointer = *it; if (pointer->GetType()==xPinEx && ((CDrawPin *)pointer)->GetPart()==OldPart) { NewPin = new CDrawPin(this); *NewPin = *((CDrawPin *)pointer); NewPin->SetPart(GetPart()); Add(NewPin); } ++ it; } } Invalidate(); }
int CTinyCadSymbolDoc::GetPartsPerPackage() { // Find out how many parts in this package int max=0; drawingIterator it = GetDrawingBegin(); while (it != GetDrawingEnd()) { CDrawingObject *pointer = *it; if (pointer->GetType()==xPinEx && ((CDrawPin *)pointer)->GetPart()>max) { max = ((CDrawPin *)pointer)->GetPart(); } ++ it; } return max + 1; }
// Remove all errors from this design void CTinyCadDoc::DeleteErrors() { // Get rid of any drawing tool SelectObject(new CDrawEditItem(this)); drawingIterator it = GetDrawingBegin(); while (it != GetDrawingEnd()) { drawingIterator current = it; ++ it; CDrawingObject *pointer = *current; if (pointer->GetType()==xError) { m_drawing.erase(current); delete pointer; } } Invalidate(); }
// Delete the selected objects! void CTinyCadDoc::SelectDelete() { if (!IsSelected()) return; CJunctionUtils j( this ); drawingIterator it = GetDrawingBegin(); while (it != GetDrawingEnd()) { drawingIterator current = it; ++ it; CDrawingObject *pointer = *current; if (IsSelected( pointer )) { if (pointer == GetSelectable()) { SetSelectable( NULL ); } j.AddObjectToTodo( pointer ); MarkDeleteForUndo( pointer ); m_drawing.erase( current ); pointer->Display(); delete pointer; } } m_selected.erase( m_selected.begin(), m_selected.end() ); // ... and perform the junction requirements... j.CheckTodoList( true ); SetModifiedFlag( TRUE ); }
// Auto anotate the design void CTinyCadView::OnSpecialAnotate() { CDlgAnotateBox theDialog(this,theASetup); // Get rid of any drawing tool GetCurrentDocument()->SelectObject(new CDrawEditItem(GetCurrentDocument())); // Do the dialog int action = theDialog.DoModal(); if (action == IDC_REF_PAINTER) { theASetup = theDialog.v; GetCurrentDocument()->SelectObject(new CDrawRefPainter(GetCurrentDocument(), theASetup.startval )); return; } else if (action !=IDOK) { return; } theASetup = theDialog.v; // Set the busy icon SetCursor( AfxGetApp()->LoadStandardCursor( IDC_WAIT ) ); // Now add/remove references CDrawMethod *thisMethod; CSymbolRecord *thisSymbol; int value=0; int part=0; BOOL IsSet,IsMatch,MissingSymbols=FALSE; for (int i = 0; i < 2; i++) { int sheet = theASetup.all_sheets ? 0 : GetDocument()->GetActiveSheetIndex(); do { drawingIterator it = GetDocument()->GetSheet(sheet)->GetDrawingBegin(); while (it != GetDocument()->GetSheet(sheet)->GetDrawingEnd()) { CDrawingObject *pointer = *it; // Look for method objects if (pointer->GetType() == xMethodEx3) { thisMethod = (CDrawMethod *)pointer; thisSymbol = thisMethod->GetSymbolData(); // If there is no symbol then cannot modify this symbol! if (thisMethod->IsNoSymbol()) { MissingSymbols = TRUE; ++ it; continue; } // Has this symbol got a reference? IsSet = thisMethod->HasRef(); switch (theASetup.reference) { case 0: // All references IsMatch = TRUE; break; case 1: // Un-numbered references IsMatch = !thisMethod->HasRef(); break; case 2: // References that match... IsMatch = theASetup.matchval == thisSymbol->reference; break; } if (IsMatch) { // First pass - we remove references if necessary, // Second pass - we add refences back in... // if (i == 0) { // Remove any matching references (if necessary) if (IsSet && (theASetup.value!=1 || thisMethod->GetRefVal()>=theASetup.startval) ) { thisMethod->RemoveReference(); } } else { // Now add back any references if (theASetup.action == 0) { if (theASetup.reference != 1) { value = (theASetup.value == 0) ? 1 : theASetup.startval; } thisMethod->AddReference( value, theASetup.all_sheets ); } } } } ++ it; } ++ sheet; } while ( theASetup.all_sheets && sheet < GetDocument()->GetNumberOfSheets() ); } // Where there any missing symbols? if (MissingSymbols) Message(IDS_MISSMETH,MB_ICONEXCLAMATION); // Restore the correct cursor SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) ); // Ensure the window is re-drawn GetCurrentDocument()->SetModifiedFlag( TRUE ); Invalidate(); }
// The code below is from the wizard but it has been customized for this // application. There is a custom code to handle WM_SIZE, WM_GESTURENOTIFY // and WM_GESTURE messages. // // Processes messages for the main window: // WM_COMMAND - process the application menu // WM_SIZE - process resizing of client window // WM_PAINT - paint the main window // WM_DESTROY - post a quit message and return // WM_GESTURENOTIFY - process a gesture notification message // WM_GESTURE - process the gesture command // in: // hWnd window handle // message message code // wParam message parameter (message-specific) // lParam message parameter (message-specific) // returns: // the result of the message processing and depends on the message sent LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_GESTURENOTIFY: { // This is the right place to define the list of gestures that this // application will support. By populating GESTURECONFIG structure // and calling SetGestureConfig function. We can choose gestures // that we want to handle in our application. In this app we // decide to handle all gestures. GESTURECONFIG gc = { 0, // gesture ID GC_ALLGESTURES, // settings related to gesture ID that are to be // turned on 0 // settings related to gesture ID that are to be // turned off }; BOOL bResult = SetGestureConfig( hWnd, // window for which configuration is specified 0, // reserved, must be 0 1, // count of GESTURECONFIG structures &gc, // array of GESTURECONFIG structures, dwIDs will be processed in the // order specified and repeated occurances will overwrite previous ones sizeof(GESTURECONFIG) // sizeof(GESTURECONFIG) ); if (!bResult) { ASSERT(L"Error in execution of SetGestureConfig" && 0); } } break; case WM_GESTURE: // The gesture processing code is implemented in the CGestureEngine // class. return g_cGestureEngine.WndProc(hWnd,wParam,lParam); break; case WM_SIZE: // resize rectangle and place it in the middle of the new client area g_cRect.ResetObject(LOWORD(lParam),HIWORD(lParam)); break; case WM_COMMAND: wmId = LOWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // Full redraw: background + rectangle g_cRect.Paint(hdc); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
void CTinyCadView::OnDraw(CDC* pDC) { //CTinyCadDoc* pDoc = GetCurrentDocument(); CDC BitmapDC; CBitmap *old_bitmap = NULL; int selected; CRect client; if (pDC->IsKindOf(RUNTIME_CLASS(CPaintDC))) { client = static_cast<CPaintDC*> (pDC)->m_ps.rcPaint; } else { GetClientRect(&client); } // Are we going to use off-screen drawing? BOOL osb = !pDC->IsPrinting() && m_use_offscreen_drawing && CreateBitmap(*pDC, client.Width(), client.Height()); if (osb) { BitmapDC.CreateCompatibleDC(pDC); old_bitmap = BitmapDC.SelectObject(&m_bitmap); } { CContext dc(osb ? &BitmapDC : pDC, GetTransform(), this); CDPoint origin = GetTransform().GetOrigin(); if (osb) { CPoint point = CPoint(-client.left, -client.top); dc.SetPixelOffset(point); } if (pDC->IsPrinting()) { dc.SetBlack(CTinyCadRegistry::GetPrintBandW()); } CDPoint Start, End; CRect rect; GetClientRect(&rect); TransformSnap snap; snap.SetGridSnap(FALSE); Start = GetTransform().DeScale(snap, CPoint(rect.left, rect.top)); End = GetTransform().DeScale(snap, CPoint(rect.right, rect.bottom)); // Is any of this region in the off-page area? if (!pDC->IsPrinting()) { // Paint the region white if (pDC->IsPrinting()) { dc.SelectBrush(cWHITE); dc.SelectPen(PS_SOLID, 1, cWHITE); } else { COLORREF col = GetCurrentDocument()->GetOptions()->GetUserColor().Get(CUserColor::BACKGROUND); dc.SelectBrush(col, 0); dc.SelectPen(PS_SOLID, 1, col); } dc.Rectangle(CDRect(Start.x - 2, Start.y - 2, End.x + 2, End.y + 2)); dc.SelectBrush(cOFFPAGE); dc.SelectPen(PS_SOLID, 1, cOFFPAGE); if (End.x > GetCurrentDocument()->GetDetails().GetPageBoundsAsPoint().x) { CDPoint a = CDPoint(GetCurrentDocument()->GetDetails().GetPageBoundsAsPoint().x, 0); dc.Rectangle(CDRect(a.x, a.y, End.x, End.y)); } if (End.y > GetCurrentDocument()->GetDetails().GetPageBoundsAsPoint().y) { CDPoint a = CDPoint(Start.x, GetCurrentDocument()->GetDetails().GetPageBoundsAsPoint().y); dc.Rectangle(CDRect(a.x, a.y, End.x, End.y)); } if (Start.x < 0) dc.Rectangle(CDRect(0, Start.y, Start.x, End.y)); if (Start.y < 0) dc.Rectangle(CDRect(Start.x, 0, End.x, Start.y)); // Fill this region with a grid double grid = GetCurrentDocument()->m_snap.GetGrid(); double SGrid = dc.GetTransform().doubleScale(grid); if (GetCurrentDocument()->GetOptions()->ShowGrid() && SGrid > 10) { double x = dc.GetTransform().GetOrigin().x; double y = dc.GetTransform().GetOrigin().y; TransformSnap s = GetCurrentDocument()->m_snap; s.SetGridSnap(TRUE); x = s.Snap(x); y = s.Snap(y); for (double xp = x >= 0 ? x : 0; xp < End.x && xp < GetCurrentDocument()->GetDetails().GetPageBoundsAsPoint().x; xp += grid) { for (double yp = y >= 0 ? y : 0; yp < End.y && yp < GetCurrentDocument()->GetDetails().GetPageBoundsAsPoint().y; yp += grid) { dc.SetPixel(CDPoint(xp, yp), 0); } } } } Start -= CDPoint(10, 10); End += CDPoint(10, 10); GetCurrentDocument()->GetSelectBegin(); drawingIterator it = GetCurrentDocument()->GetDrawingBegin(); while (it != GetCurrentDocument()->GetDrawingEnd()) { CDrawingObject *obj = *it; selected = !pDC->IsPrinting() && GetCurrentDocument()->IsSelected(obj); paint_options options = selected ? draw_selected : draw_normal; if (!pDC->IsPrinting() || !obj->IsConstruction()) { if (pDC->IsPrinting() || obj->IsInside(Start.x, End.x, Start.y, End.y)) { obj->Paint(dc, options); } } ++it; } // Now draw the selectable object, so it stands out... CDrawingObject *obj = GetCurrentDocument()->GetSelectable(); if (obj != NULL && !GetCurrentDocument()->IsSelected(obj)) { paint_options options = draw_selectable; GetCurrentDocument()->GetSelectable()->Paint(dc, options); } // If only one item is selected then just draw its handles now if (GetCurrentDocument()->IsSingleItemSelected()) { GetCurrentDocument()->GetSingleSelectedItem()->PaintHandles(dc); } // if necessary turn back on the current object to be edited if (GetCurrentDocument()->GetEdit() != NULL) { //ATLTRACE2("TinyCadView::GetCurrentDocument->GetEdit->Paint(dc, draw_selected=%d)\n",draw_selected); GetCurrentDocument()->GetEdit()->Paint(dc, draw_selected); } // Draw the design details GetCurrentDocument()->Display(dc); } if (osb) { pDC->BitBlt(client.left, client.top, client.Width(), client.Height(), &BitmapDC, 0, 0, SRCCOPY); BitmapDC.SelectObject(old_bitmap); } }
//------------------------------------------------------------------------- void CTinyCadDoc::SaveXML(CXMLWriter &xml, drawingCollection &drawing, BOOL Details, BOOL SaveSelect, BOOL SaveResources ) { // Write the objects to the file try { xml.addTag(GetXMLTag()); // If necessary write the header stamp if (Details) { xml.addTag(_T("NAME")); xml.addChildData( m_sheet_name ); xml.closeTag(); xml.addTag(_T("DETAILS")); m_oDetails.WriteXML( xml ); m_snap.SaveXML( xml ); xml.closeTag(); } if (SaveResources) { // Find out which resources are in use for( drawingIterator i = drawing.begin(); i != drawing.end(); i++ ) { (*i)->TagResources(); } // Save the resource details details theOptions.SaveFontsXML(xml); theOptions.SaveStylesXML(xml); theOptions.SaveFillStylesXML(xml); theOptions.SaveMetaFilesXML(xml); } // Only save the symbols if we are not saving // to a library or the header... if (Details) { theOptions.SaveSymbolsXML(xml); } if (Details) { theOptions.WriteXML( xml) ; } for( drawingIterator i = drawing.begin(); i != drawing.end(); i++ ) { CDrawingObject* obj = *i; if (obj->GetType() != xError && (Details || !obj->IsConstruction()) && (!SaveSelect || IsSelected( obj )) ) { // Now save the actual object data obj->SaveXML(xml); } } xml.closeTag(); } catch ( CException *e) { // Could not save the file properly e->ReportError(); e->Delete(); } }
////// Load a design from a file, loaded design will be selected ////// BOOL CTinyCadDoc::ReadFileXML(CXMLReader &xml, BOOL Details, drawingCollection &drawing, BOOL AlreadyStarted) { try { // Read in the first item... CString name; bool sheets = false; if (!AlreadyStarted) { xml.nextTag( name ); if (name == "TinyCADSheets") { xml.intoTag(); sheets = true; // We must search for the first TinyCAD section while (xml.nextTag( name ) && name != GetXMLTag()) { } } // Check we are at the right point if (name != GetXMLTag()) { Message(IDS_ABORTVERSION,MB_ICONEXCLAMATION); return FALSE; } } BOOL ResetMerge = TRUE; xml.intoTag(); while ( xml.nextTag( name ) ) { // Save the old layer setting CDrawingObject *obj = NULL; if (name == "DETAILS" ) { if (Details) { GetDetails().ReadXML( xml, m_snap ); } } else if (name == "NAME") { if (Details) { xml.getChildData( m_sheet_name ); } } else if (name == "GRID") { if (Details) { m_snap.LoadXML( xml ); } } else if (name == "FONT") { if (ResetMerge) { theOptions.ResetMerge(); ResetMerge = FALSE; } theOptions.LoadFontXML(xml); } else if (name == "STYLE") { if (ResetMerge) { theOptions.ResetMerge(); ResetMerge = FALSE; } theOptions.LoadStyleXML(xml); } else if (name == "FILL") { if (ResetMerge) { theOptions.ResetMerge(); ResetMerge = FALSE; } theOptions.LoadFillStyleXML(xml); } else if (name == "META" || name == "IMAGE") { if (ResetMerge) { theOptions.ResetMerge(); ResetMerge = FALSE; } theOptions.LoadMetaFileXML(xml); } else if (name == "SYMBOLDEF") { if (ResetMerge) { theOptions.ResetMerge(); ResetMerge = FALSE; } theOptions.LoadSymbolXML(xml); } else if (name == "OPTIONS") { theOptions.ReadXML( xml ); } else if (name == CDrawBusSlash::GetXMLTag()) { obj = new CDrawBusSlash(this); } else if (name == CDrawTag::GetXMLTag()) { obj = new CDrawTag(this); } else if (name == CDrawJunction::GetXMLTag()) { obj = new CDrawJunction(this); } else if (name == CDrawLine::GetXMLTag(xBus)) { obj = new CDrawLine(this, xBus); } else if (name == CDrawLine::GetXMLTag(xWire)) { obj = new CDrawLine(this, xWire); } else if (name == CDrawLine::GetXMLTag(xLineEx2)) { obj = new CDrawLine(this, xLineEx2); } else if (name == CDrawMetaFile::GetXMLTag()) { obj = new CDrawMetaFile(this); } else if (name == CDrawMethod::GetXMLTag()) { obj = new CDrawMethod(this); } else if (name == CDrawHierarchicalSymbol::GetXMLTag()) { obj = new CDrawHierarchicalSymbol(this); } else if (name == CDrawNoConnect::GetXMLTag()) { obj = new CDrawNoConnect(this); } else if (name == CDrawPin::GetXMLTag()) { obj = new CDrawPin(this); } else if (name == CDrawRuler::GetXMLTag()) { obj = new CDrawRuler(this, FALSE); } else if (name == CDrawSquare::GetXMLTag( TRUE )) { obj = new CDrawSquare(this, xSquareEx3); } else if (name == CDrawSquare::GetXMLTag( FALSE )) { obj = new CDrawSquare(this, xCircleEx3); } else if (name == CDrawText::GetXMLTag(xTextEx2)) { obj = new CDrawText(this, xTextEx2); } else if (name == CDrawText::GetXMLTag(xBusNameEx)) { obj = new CDrawText(this, xBusNameEx); } else if (name == CDrawLabel::GetXMLTag()) { obj = new CDrawLabel(this); } else if (name == CDrawPolygon::GetXMLTag()) { obj = new CDrawPolygon(this); } else if (name == CDrawPower::GetXMLTag()) { obj = new CDrawPower(this); } if (obj != NULL) { // Load this object... obj->LoadXML( xml ); // Now add object to linked list drawing.insert( drawing.end(), obj ); } } xml.outofTag(); if (sheets) { xml.outofTag(); } } catch( CException *e ) { e->ReportError(); e->Delete(); return FALSE; } return drawing.size() > 0; }
//-- Load a design from a file, loaded design will be selected BOOL CTinyCadDoc::ReadFile(CStream &theArchive, BOOL Details, drawingCollection &drawing) { try { // Save the old layer setting CDrawingObject* obj = NULL; BYTE tp = xNULL; CHeaderStamp oHeader; LONG pos = theArchive.GetPos(); oHeader.Read( theArchive ); if( ! oHeader.IsChecked(false) ) { // Perhaps this is XML? theArchive.Seek(pos); CXMLReader xml( &theArchive ); return ReadFileXML( xml, Details, drawing, FALSE ); } while (tp!=xEndFile) { theArchive >> tp; switch (tp) { case xDesignInformation: GetDetails().Read( theArchive ); break; case xDesignInformation2: GetDetails().ReadEx( theArchive ); m_snap.Load( theArchive, Details ); break; case xOptions: if( Details ) { theOptions.ReadNative( theArchive ); } else { COption().ReadNative( theArchive ); } obj = NULL; break; case xFont: theOptions.LoadFonts(theArchive); obj = NULL; break; case xLineStyle: theOptions.LoadStyles(theArchive); obj = NULL; break; case xFillStyle: theOptions.LoadFillStyles(theArchive); obj = NULL; break; case xMetaFiles: theOptions.LoadMetaFiles(theArchive); obj = NULL; break; case xSymbols: theOptions.LoadSymbols(theArchive); obj = NULL; break; case xLayerTable: { // Read in the number of Layers in this list CString theNewName; WORD NumberOfResources; theArchive >> NumberOfResources; hRESOURCE OldResourceNumber = 0; while (NumberOfResources > 0) { theArchive >> OldResourceNumber; theArchive >> theNewName; NumberOfResources--; } obj = NULL; } break; case xRuler: obj = new CDrawRuler(this,FALSE); break; case xBus: obj = new CDrawLine(this,xBus); break; case xWire: obj = new CDrawLine(this,xWire); break; case xBusName: obj = new CDrawText(this,xBusName); break; case xBusNameEx: obj = new CDrawText(this,xBusNameEx); break; case xLabel: obj = new CDrawLabel(this); break; case xLabelEx: obj = new CDrawLabel(this); break; case xLabelEx2: obj = new CDrawLabel(this); break; case xJunction: obj = new CDrawJunction(this); break; case xNoConnect: obj = new CDrawNoConnect(this); break; case xBusSlash: obj = new CDrawBusSlash(this); break; case xPower: obj = new CDrawPower(this); break; case xPin: case xPinEx: obj = new CDrawPin(this); break; case xLine: obj = new CDrawPolygon(this,xLine); break; case xLineEx: obj = new CDrawPolygon(this,xLineEx); break; case xLineEx2: obj = new CDrawPolygon(this,xLineEx2); break; case xPolygon: obj = new CDrawPolygon(this,xPolygon); break; case xDash: obj = new CDrawPolygon(this,xDash); break; case xText: // The old text type obj = new CDrawText(this,xText); break; case xTextEx: obj = new CDrawText(this,xTextEx); break; case xTextEx2: obj = new CDrawText(this,xTextEx2); break; case xCircle: case xCircleEx: case xCircleEx2: case xCircleEx3: obj = new CDrawSquare(this,xCircleEx3); break; case xSquare: case xSquareEx: case xSquareEx2: case xSquareEx3: obj = new CDrawSquare(this,xSquareEx3); break; case xArc: case xArcEx: case xArcEx2: obj = new CDrawPolygon(this,static_cast<ObjType>(tp)); break; case xMethod: // The old method type case xMethodEx: case xMethodEx2: case xMethodEx3: obj = new CDrawMethod(this); break; case xTag: obj = new CDrawTag(this); break; case xMetaFile: obj = new CDrawMetaFile(this); break; default: obj = NULL; break; } if (obj!=NULL) { // Provide special handling for old objects switch (tp) { case xSquare: case xSquareEx: case xCircle: case xCircleEx: ((CDrawSquare *)obj)->OldLoad(theArchive,tp); break; case xCircleEx2: case xSquareEx2: ((CDrawSquare *)obj)->OldLoad2(theArchive); break; case xMethod: ((CDrawMethod *)obj)->OldLoad(theArchive); break; case xMethodEx: ((CDrawMethod *)obj)->OldLoad2(theArchive); break; case xMethodEx2: ((CDrawMethod *)obj)->OldLoad3(theArchive); break; case xPin: ((CDrawPin *)obj)->OldLoad(theArchive); break; case xLabel: case xLabelEx: case xLabelEx2: ((CDrawLabel *)obj)->Load(theArchive,(ObjType)tp); break; default: obj->Load(theArchive); break; } // Now add object to linked list drawing.insert( drawing.end(), obj ); } } } catch( CException *e) { CString s; CString msg; e->GetErrorMessage( msg.GetBuffer(256), 256, NULL ); msg.ReleaseBuffer(); s.Format(_T("Cannot load file.\r\n%s"), msg ); AfxMessageBox( s ); e->Delete(); } return drawing.size() > 0; }
// Redo the last action void CTinyCadDoc::Redo() { SetSelectable( NULL ); BOOL action_taken = FALSE; // Is this possible? while (CanRedo() && !action_taken) { m_undo_level ++; // Re-apply all of the changes we have done at this level CDocUndoSet &s = m_undo[ m_undo_level ]; // Go through the list of action and redo each one // CDocUndoSet::actionCollection::iterator act_it = s.m_actions.begin(); while (act_it != s.m_actions.end()) { CDocUndoSet::CDocUndoAction &act = *act_it; // Look up this item from the index... drawingCollection::iterator it = m_drawing.begin(); int index = act.m_index; while (index > 0 && it != m_drawing.end()) { ++ it; -- index; } if (it != m_drawing.end()) { (*it)->Display(); } act.m_object->Display(); switch (act.m_action) { case CDocUndoSet::Deletion: // We must re-delete the deleted objects delete *it; m_drawing.erase( it ); action_taken = TRUE; break; case CDocUndoSet::Addition: // We must re-insert the additions m_drawing.insert( it, Dup(act.m_object) ); action_taken = TRUE; break; case CDocUndoSet::Change: // We convert the old objects into the new objects... { // Keep a copy for the redo... CDrawingObject *copy = Dup(*it); delete *it; copy->Display(); *it = act.m_object; act.m_object = copy; } action_taken = TRUE; break; } ++ act_it; } } }
// Create netlist and output as a PCB file void CNetList::WriteNetListFileTinyCAD( CTinyCadMultiDoc *pDesign, const TCHAR *filename ) { FILE *theFile; errno_t err; err = _tfopen_s(&theFile, filename,_T("w")); if ((theFile == NULL) || (err != 0)) { Message(IDS_CANNOTOPEN); return; } // Set the Busy icon SetCursor( AfxGetApp()->LoadStandardCursor( IDC_WAIT ) ); // Get the net list MakeNet( pDesign ); _ftprintf(theFile,NetComment _T(" ====+ Net List for %s +====\n\n"), pDesign->GetPathName() ); _ftprintf(theFile,NetComment _T(" ======+ The component list\n\n")); // Keep track of the references we have outputted... std::set<CString> referenced; // Do this for all of the files in the imports list... fileCollection::iterator fi = m_imports.begin(); for (;fi != m_imports.end(); ++ fi) { CTinyCadMultiDoc *dsn = pDesign; if ((*fi)->m_file_name_index != 0) { dsn = (*fi)->m_pDesign; } // Generate a component for every sheet in this design for (int i = 0; i < dsn->GetNumberOfSheets(); i++) { drawingIterator it = dsn->GetSheet(i)->GetDrawingBegin(); while (it != dsn->GetSheet(i)->GetDrawingEnd()) { CDrawingObject *pointer = *it; if (pointer->GetType() == xMethodEx3) { CDrawMethod *pMethod = static_cast<CDrawMethod *>(pointer); CString Name = pMethod->GetField(CDrawMethod::Name); CString Ref = pMethod->GetRefSheet(m_prefix_references,m_prefix_import,(*fi)->m_file_name_index,i+1); // Do we need to output this part? if (referenced.find( Ref ) == referenced.end()) { referenced.insert( Ref ); _ftprintf(theFile,_T("COMPONENT '%s' = %s\n"),Ref,Name); // Now write it it's "other" references for (int i = 2; i < pMethod->GetFieldCount(); i++) { _ftprintf(theFile,_T("\tOPTION '%s' = %s\n"),pMethod->GetFieldName(i), pMethod->GetField(i) ); } } } ++ it; } } } _ftprintf(theFile,_T("\n\n") NetComment _T(" ======+ The net list\n\n")); int Label = 0; netCollection::iterator nit = m_nets.begin(); while (nit != m_nets.end()) { nodeVector::iterator nv_it = (*nit).second.begin(); CString theLine,theLabel; if (nv_it != (*nit).second.end()) { theLine = ""; BOOL first = TRUE,PrintLine=FALSE, Labeled = FALSE; while (nv_it != (*nit).second.end()) { CNetListNode& theNode = *nv_it; ++ nv_it; if (theNode.getLabel() != "" && !Labeled) { theLabel = theNode.getLabel(); Labeled = TRUE; } else { CString add; if (!theNode.getLabel().IsEmpty()) { add = theNode.getLabel(); } else if (!theNode.m_reference.IsEmpty()) { add.Format(_T("(%s,%s)"), theNode.m_reference, theNode.m_pin ); } if (!add.IsEmpty()) { if (first) { first = FALSE; } else { theLine += _T(","); } theLine += add; PrintLine=TRUE; } } } if (PrintLine) { _ftprintf(theFile,_T("NET ")); if (Labeled) _ftprintf(theFile,_T("'%s'"),theLabel); else _ftprintf(theFile,_T("'N%06d'"),Label++); _ftprintf(theFile,_T(" = %s\n"),theLine); } } ++ nit; } SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) ); fclose(theFile); }
// Create netlist and output as a SPICE file void CNetList::WriteSpiceFile( CTinyCadMultiDoc *pDesign, const TCHAR *filename ) { // Open the filename for the spice file FILE *theFile; errno_t err; err = _tfopen_s(&theFile, filename,_T("w")); if ((theFile == NULL) || (err != 0)) { Message(IDS_CANNOTOPEN); return; } // Output the standard header comment - expected on line 1 by some Spice engines _ftprintf(theFile,_T("* Schematics Netlist *\n")); createErrorFile( filename ); _ftprintf(m_err_file,_T("Results of Spice file generation for %s\n\n"), pDesign->GetPathName() ); // Set the Busy icon SetCursor( AfxGetApp()->LoadStandardCursor( IDC_WAIT ) ); // Create the net list m_prefix_import = TRUE; m_prefix_references = TRUE; MakeNet( pDesign ); // Now we have the net list we must convert it into a file suitable for // spice... // // The netlist represents a single vector per net, however, spice requires // a vector per symbol. We have to rotate the array, so that we have one // entry in our vector for each of the symbols in our drawing.... // typedef std::map<CString,CNetListSymbol> symbolCollection; symbolCollection symbols; labelCollection labels; netCollection::iterator nit = m_nets.begin(); while (nit != m_nets.end()) { nodeVector::iterator nv_it = (*nit).second.begin(); while (nv_it != (*nit).second.end()) { CNetListNode& theNode = *nv_it; ++ nv_it; // Is this node a symbol? if (!theNode.m_reference.IsEmpty() && theNode.m_pMethod->GetType() == xMethodEx3 ) { // Yes, so update the pin allocations in the symbol map... CNetListSymbol &symbol = symbols[ theNode.m_reference ]; symbol.m_pins[ theNode.m_pin ] = theNode.m_NetList; symbol.m_pMethod = theNode.m_pMethod; } // Is this node a label? if (!theNode.getLabel().IsEmpty()) { // Yes, so update the label collection labels[ theNode.m_NetList ] = theNode.getLabel(); } } ++ nit; } // // We scan the symbols array and extract any file imports // That we need from the fields of the symbols... // symbolCollection::iterator sit = symbols.begin(); typedef std::set<CString> strings; typedef std::vector<strings> string_collection; string_collection prolog_lines; string_collection epilog_lines; prolog_lines.resize( 10 ); epilog_lines.resize( 10 ); // Do this for all of the files in the imports list... fileCollection::iterator fi = m_imports.begin(); for (;fi != m_imports.end(); ++ fi) { CTinyCadMultiDoc *dsn = pDesign; if ((*fi)->m_file_name_index != 0) { dsn = (*fi)->m_pDesign; } // Generate a component for every sheet in this design for (int sheet = 0; sheet < dsn->GetNumberOfSheets(); sheet++) { drawingIterator it = dsn->GetSheet(sheet)->GetDrawingBegin(); while (it != dsn->GetSheet(sheet)->GetDrawingEnd()) { CDrawingObject *pointer = *it; if (pointer->GetType() == xMethodEx3) { CDrawMethod *pMethod = static_cast<CDrawMethod *>(pointer); // Search this symbols fields and extract the SPICE_IMPORT field... // CString spice_prolog; CString spice_epilog; int spice_pro_priority = 5; int spice_epi_priority = 5; for (int j = 0; j < pMethod->GetFieldCount(); j++) { CString field = pMethod->GetFieldName(j); if (field.CompareNoCase(AttrSpiceProlog) == 0) { CNetListSymbol symbol( (*fi)->m_file_name_index, sheet, pMethod ); spice_prolog = expand_spice( (*fi)->m_file_name_index, sheet, symbol, labels, pMethod->GetField(j) ); } else if (field.CompareNoCase(AttrSpiceEpilog) == 0) { CNetListSymbol symbol( (*fi)->m_file_name_index, sheet, pMethod ); spice_epilog = expand_spice( (*fi)->m_file_name_index, sheet, symbol, labels, pMethod->GetField(j) ); } else if (field.CompareNoCase(AttrSpicePrologPri) == 0) { spice_pro_priority = _tstoi( pMethod->GetField(j) ); if (spice_pro_priority < 0 || spice_pro_priority > 9) { spice_pro_priority = 5; } } else if (field.CompareNoCase(AttrSpiceEpilogPri) == 0) { spice_epi_priority = _tstoi( pMethod->GetField(j) ); if (spice_epi_priority < 0 || spice_epi_priority > 9) { spice_epi_priority = 5; } } } // Prologue... strings &prolog = prolog_lines[ spice_pro_priority ]; if (prolog.find( spice_prolog ) == prolog.end()) { // Not included yet... prolog.insert( spice_prolog ); } // Epilog.. strings &epilog = epilog_lines[ spice_pro_priority ]; if (epilog.find( spice_epilog ) == epilog.end()) { // Not included yet... epilog.insert( spice_epilog ); } } ++ it; } } } // We have extracted the prologue, so now output it in the // order of priority (0 being first...) int priority; for (priority = 0; priority < 10; priority ++) { strings &s = prolog_lines[ priority ]; strings::iterator i = s.begin(); while (i != s.end()) { _ftprintf( theFile, _T("%s\n"), *i ); ++ i; } } // We now have the netlist in the form we require it, so // let us now output the symbols in the correct SPICE format... // sit = symbols.begin(); while (sit != symbols.end()) { CString reference = (*sit).first; CNetListSymbol &symbol = (*sit).second; CDrawMethod* pMethod = symbol.m_pMethod; int sheet = symbol.m_sheet; int file_name_index = symbol.m_file_name_index; // Here is the data we are going to extract from // the symbol's fields... CString spice = ""; // Search this symbols fields and extract the SPICE field... // int i; for (i = 0; i < pMethod->GetFieldCount(); i++) { if (pMethod->GetFieldName(i).CompareNoCase(AttrSpice) == 0) { spice = pMethod->GetField(i); } } // Now output the SPICE model line if (!spice.IsEmpty()) { _ftprintf(theFile,_T("%s\n"), expand_spice( file_name_index, sheet, symbol, labels, spice ) ); } else { _ftprintf(theFile,_T("NO_MODEL\n") ); writeError(_T("%s: %s on sheet %d has no model\n"), symbol.m_pMethod->GetRef(), symbol.m_pMethod->GetName(), sheet ); } ++ sit; } // Now write out the epilog for (priority = 9; priority >= 0; priority --) { strings &s = epilog_lines[ priority ]; strings::iterator i = s.begin(); while (i != s.end()) { _ftprintf( theFile,_T("%s\n"), *i ); ++ i; } } SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) ); fclose(theFile); reopenErrorFile( true ); }
// Perform the work of making a netlist from a single sheet in this design... void CNetList::MakeNetForSheet( fileCollection &imports, int file_index_id, int &file_name_index, int sheet, CTinyCadDoc *pDesign ) { // Get rid of any old data m_CurrentNet = 1; m_nodes.erase( m_nodes.begin(), m_nodes.end() ); m_nets.erase( m_nets.begin(), m_nets.end() ); // Here is some temporary data for this function typedef std::map<CString,int> stringCollection; stringCollection Powers; stringCollection Connected; // Search for nodes, and build the node tree drawingIterator it = pDesign->GetDrawingBegin(); for (;it != pDesign->GetDrawingEnd(); ++ it ) { CDrawingObject *ObjPtr = *it; stringCollection::iterator found; int hold; CDPoint tr; switch (ObjPtr->GetType()) { case xHierarchicalSymbol: { CDrawHierarchicalSymbol *pSymbol = static_cast<CDrawHierarchicalSymbol*>(ObjPtr); // Try and stop recursion by limiting the number of imports if (imports.size() > 100) { AfxMessageBox( IDS_RECURSION ); continue; } // Push back this filename into the list of extra imports CImportFile *f = new CImportFile; ++ file_name_index; f->m_file_name_index = file_name_index; if (f->Load( pSymbol->GetFilename() ) ) { imports.push_back( f ); // Now search the symbol for pins to link the other symbols to drawingCollection method; pSymbol->ExtractSymbol(tr,method); drawingIterator it = method.begin(); while ( it != method.end() ) { CDrawingObject *pointer = *it; if (pointer->GetType()==xPinEx) { CDrawPin *thePin = static_cast<CDrawPin*>(pointer); // This in effect labels the node with the new node name... CNetListNode n( file_name_index, sheet, thePin, thePin->GetActivePoint(pSymbol) ); n.setLabel( thePin->GetPinName() ); n.m_reference = pSymbol->GetRefSheet(m_prefix_references,m_prefix_import,file_index_id,sheet); n.m_pin = thePin->GetNumber(); n.m_pMethod = pSymbol; Add(n); } ++ it; } } else { delete f; } } break; case xMethodEx3: #define thePin ((CDrawPin*)pointer) #define theMethod ((CDrawMethod*)ObjPtr) { drawingCollection method; ((CDrawMethod *)ObjPtr)->ExtractSymbol(tr,method); drawingIterator it = method.begin(); while ( it != method.end() ) { CDrawingObject *pointer = *it; if (pointer->GetType()==xPinEx && !(thePin->IsPower()) ) { CNetListNode n( file_index_id, sheet, thePin,thePin->GetActivePoint(theMethod)); n.m_reference = theMethod->GetRefSheet(m_prefix_references,m_prefix_import,file_index_id,sheet); n.m_pin = thePin->GetNumber(); n.m_pMethod = theMethod; Add(n); } ++ it; } // Has this symbol had it's power connected? if (Connected.find(theMethod->GetRefSheet(m_prefix_references,m_prefix_import,file_index_id,sheet)) == Connected.end()) { Connected[ theMethod->GetRefSheet(m_prefix_references,m_prefix_import,file_index_id,sheet) ] = TRUE; drawingCollection method; ((CDrawMethod *)ObjPtr)->ExtractSymbol(tr,method); drawingIterator it = method.begin(); while (it!=method.end()) { CDrawingObject *pointer = *it; if (pointer->GetType()==xPinEx && thePin->IsPower()) { CNetListNode n(file_index_id, sheet, thePin,thePin->GetActivePoint(theMethod) ); n.m_reference = theMethod->GetRefSheet(m_prefix_references,m_prefix_import,file_index_id,sheet); n.m_pin = thePin->GetNumber(); n.m_pMethod = theMethod; // Look up the netlist this power belongs to found = Powers.find( thePin->GetPinName() ); if (found != Powers.end()) n.m_NetList = (*found).second; hold = Add(n); if (found == Powers.end()) Powers[thePin->GetPinName()] = hold; } ++ it; } } } break; case xNoConnect: Add(CNetListNode(file_index_id, sheet, ObjPtr,ObjPtr->m_point_a)); break; case xJunction: Add(CNetListNode(file_index_id, sheet, ObjPtr,ObjPtr->m_point_a)); break; case xPower: { CNetListNode n(file_index_id, sheet, ObjPtr,ObjPtr->m_point_a); n.setLabel( ((CDrawPower *)ObjPtr)->GetValue() ); // Does this power item exist? found = Powers.find(((CDrawPower *)ObjPtr)->GetValue()); if (found != Powers.end()) n.m_NetList = (*found).second; hold = Add(n); if (found == Powers.end()) Powers[((CDrawPower *)ObjPtr)->GetValue()] = hold; } break; case xWire: { CNetListNode n(file_index_id, sheet, ObjPtr,ObjPtr->m_point_a); hold = Add(n); } { CNetListNode n(file_index_id, sheet, ObjPtr,ObjPtr->m_point_b); n.m_NetList = hold; Add(n); } break; } } // Search for junctions and connect together it = pDesign->GetDrawingBegin(); while (it != pDesign->GetDrawingEnd()) { CDrawingObject *ObjPtr = *it; // Search for junctions if (ObjPtr->GetType() == xJunction) { // Find out which netlist was assigned to this point CDPoint a = ObjPtr->m_point_a; int NetNumber = m_nodes[ a ]; // Look for wires which cross this junction drawingIterator search_it = pDesign->GetDrawingBegin(); while (search_it != pDesign->GetDrawingEnd()) { CDrawingObject *search = *search_it; // Find the wires // If the wire has an end at this junction then it is already connected if (search->GetType()==xWire && search->m_point_a!=a && search->m_point_b!=a) { // Is this point on this wire? CLineUtils l( search->m_point_a, search->m_point_b ); double distance_along_a; if (l.IsPointOnLine( a, distance_along_a )) { CNetListNode n(file_index_id, sheet, NULL,search->m_point_a); n.m_NetList = NetNumber; NetNumber = Add(n); } } ++ search_it; } } ++ it; } // Search for labels and connect to their respective lines stringCollection labels; it = pDesign->GetDrawingBegin(); while (it != pDesign->GetDrawingEnd()) { CDrawingObject *ObjPtr = *it; // Search for junctions if (ObjPtr->GetType() == xLabelEx2) { CDPoint a = static_cast<CDrawLabel*>(ObjPtr)->GetLabelPoint(); // Search for a wire this label is connect to // Only atempt to connect to a single wire drawingIterator search_it = pDesign->GetDrawingBegin(); while (search_it != pDesign->GetDrawingEnd()) { CDrawingObject *search = *search_it; if (search->GetType()==xWire && search->IsInside(a.x,a.x,a.y,a.y)) { a = search->m_point_a; break; } ++ search_it; } // Look up this label CNetListNode n(file_index_id, sheet, ObjPtr,a); n.setLabel( ((CDrawLabel *)ObjPtr)->GetValue() ); // Has this label already been assigned a netlist? stringCollection::iterator found = labels.find(((CDrawLabel *)ObjPtr)->GetValue()); if (found!=labels.end()) { n.m_NetList = (*found).second; n.setLabel( _T("") ); } int hold = Add(n); // If there was no netlist write it back... if (found == labels.end()) labels[ ((CDrawLabel *)ObjPtr)->GetValue()] = hold; } ++ it; } // Our work with the nodes map is complete, so we can discard // it now... m_nodes.erase( m_nodes.begin(), m_nodes.end() ); }
CDPoint CTinyCadDoc::GetStickyPoint( CDPoint q, BOOL pins, BOOL wires, BOOL &is_stuck, BOOL &is_junction ) { CDPoint r(0,0); bool first = true; double min_distance = 0; int items = 0; int range = GetOption().GetAutoSnapRange(); if (!GetOption().GetAutoSnap()) { is_stuck = FALSE; is_junction = FALSE; return q; } // Search for methods, and look at their pins drawingIterator it = GetDrawingBegin(); while (it != GetDrawingEnd()) { CDrawingObject *ObjPtr = *it; switch (ObjPtr->GetType()) { case xWire: #define theLine ((CDrawLine*)ObjPtr) if (wires) { CDPoint d; CLineUtils l( theLine->m_point_a, theLine->m_point_b ); double distance = l.DistanceFromPoint( q, d ); if (d == r) { items ++; } if (first || distance < min_distance) { if (r != d) { // have we split this wire? if (d != theLine->m_point_a && d != theLine->m_point_b) { items = 2; } else { items = 1; } } r = d; first = false; min_distance = distance; } } break; default: if (pins) { CDRect s( ObjPtr->m_point_a.x, ObjPtr->m_point_a.y, ObjPtr->m_point_b.x, ObjPtr->m_point_b.y ); s.NormalizeRect(); s.left -= range * 2; s.right += range * 2; s.bottom += range * 2; s.top -= range * 2; if (s.PtInRect(q)) { CActiveNode a; ObjPtr->GetActiveListFirst( a ); while (ObjPtr->GetActive(a)) { // This is a valid pin... CDPoint d = a.m_a; double dx = d.x - q.x; double dy = d.y - q.y; double distance = sqrt(dx*dx + dy*dy); if (r == d) { items ++; } if (first || distance < min_distance) { if (r != d) { items = 1; } r = d; first = false; min_distance = distance; } } } } break; } ++ it; } if (!first && min_distance < GetOption().GetAutoSnapRange()) { is_stuck = TRUE; is_junction = GetOption().GetAutoJunc() ? items > 1 : FALSE; return r; } else { is_junction = FALSE; is_stuck = FALSE; } return q; }
// Create netlist and output as a PCB file (PADS-PCB) void CNetList::WriteNetListFilePADS( CTinyCadMultiDoc *pDesign, const TCHAR *filename ) { FILE *theFile; errno_t err; err = _tfopen_s(&theFile, filename,_T("w")); if ((theFile == NULL) || (err != 0)) { Message(IDS_CANNOTOPEN); return; } // Set the Busy icon SetCursor( AfxGetApp()->LoadStandardCursor( IDC_WAIT ) ); // Get the net list MakeNet( pDesign ); _ftprintf(theFile,_T("*PADS-PCB*\n")); _ftprintf(theFile,_T("*PART*\n")); // Keep track of the references we have outputted... std::set<CString> referenced; // Do this for all of the files in the imports list... fileCollection::iterator fi = m_imports.begin(); for (;fi != m_imports.end(); ++ fi) { CTinyCadMultiDoc *dsn = pDesign; if ((*fi)->m_file_name_index != 0) { dsn = (*fi)->m_pDesign; } // Generate a component for every sheet in this design for (int i = 0; i < dsn->GetNumberOfSheets(); i++) { drawingIterator it = dsn->GetSheet(i)->GetDrawingBegin(); while (it != dsn->GetSheet(i)->GetDrawingEnd()) { CDrawingObject *pointer = *it; if (pointer->GetType() == xMethodEx3) { CDrawMethod *pMethod = static_cast<CDrawMethod *>(pointer); CString Ref = pMethod->GetRefSheet(m_prefix_references,m_prefix_import,(*fi)->m_file_name_index,i+1); // Do we need to output this part? if (referenced.find( Ref ) == referenced.end()) { referenced.insert( Ref ); CString Package = _T("This part has no 'Package' attribute"); for (int i = 2; i < pMethod->GetFieldCount(); i++) { if (pMethod->GetFieldName(i).CompareNoCase(_T("package")) == 0) { Package = pMethod->GetField(i); } } // Pad to correct length... do { Ref = Ref + _T(" "); } while (Ref.GetLength() < 8); _ftprintf(theFile,_T("%s%s\n"), Ref, Package); } } ++ it; } } } _ftprintf(theFile,_T("\n*NET*\n")); int Label = 0; netCollection::iterator nit = m_nets.begin(); while (nit != m_nets.end()) { nodeVector::iterator nv_it = (*nit).second.begin(); CString theLine,theLabel; if (nv_it != (*nit).second.end()) { theLine = _T(""); BOOL first = TRUE, Labeled = FALSE; int len = 0; int count = 0; while (nv_it != (*nit).second.end()) { CNetListNode& theNode = *nv_it; ++ nv_it; if (theNode.getLabel() != _T("") && !Labeled) { theLabel = theNode.getLabel(); Labeled = TRUE; } else { CString add; if (!theNode.getLabel().IsEmpty()) { // NOT FOR PADS: add = theNode.getLabel(); } else if (!theNode.m_reference.IsEmpty()) { add.Format(_T("%s.%s"), theNode.m_reference, theNode.m_pin ); } if (!add.IsEmpty()) { len += add.GetLength(); if (len > 127) { theLine += _T("\n"); len = add.GetLength(); first = TRUE; } if (first) { first = FALSE; } else { theLine += " "; len ++; } theLine += add; ++ count; } } } if (count > 1) { _ftprintf(theFile,_T("*SIGNAL* ")); if (Labeled) _ftprintf(theFile,_T("%s"), theLabel); else _ftprintf(theFile,_T("N%06d"),Label++); _ftprintf(theFile,_T("\n%s\n"), theLine); } } ++ nit; } _ftprintf(theFile,_T("*END*\n")); SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) ); fclose(theFile); }
void CTinyCadView::OnSpecialCheck() { // Get rid of any drawing tool GetCurrentDocument()->SelectObject(new CDrawEditItem(GetCurrentDocument())); CDlgERCBox theDialog; static union { ErrorTest e; WORD i; } theErrorTest; theErrorTest.i = CTinyCadRegistry::GetInt("ERC", 0xffff); // Get the user's options theDialog.SetErrorTest(theErrorTest.e); if (theDialog.DoModal() != IDOK) { return; } theErrorTest.e = theDialog.GetErrorTest(); CTinyCadRegistry::Set("ERC",theErrorTest.i); // Set the Busy icon SetCursor( AfxGetApp()->LoadStandardCursor( IDC_WAIT ) ); // Generate the netlist CNetList netlist; netlist.m_follow_imports = false; CTinyCadMultiDoc *pDoc = static_cast<CTinyCadMultiDoc*>(GetDocument()); netlist.MakeNet( pDoc ); netCollection *nets = &netlist.m_nets; // Delete all the errors which are currently in the design theERCListBox.Close(); // GetCurrentDocument()->DeleteErrors(); theERCListBox.Open( pDoc ); int CurrentError = 0; // Scan the design for duplicated references if ((theErrorTest.e).DupRef) { std::set<CString> refs; CString last = ""; for (int i = 0; i < pDoc->GetNumberOfSheets(); i++) { drawingIterator it = pDoc->GetSheet(i)->GetDrawingBegin(); while (it != pDoc->GetSheet(i)->GetDrawingEnd()) { CDrawingObject *pointer = *it; if (pointer->GetType()==xMethodEx3) { CString ref = static_cast<CDrawMethod *>(pointer)->GetField(CDrawMethod::Ref); if (refs.find( ref ) != refs.end()) { // We have a duplicate... CString buffer; buffer.LoadString( ERR_DUPREF ); pDoc->GetSheet(i)->Add(new CDrawError(pDoc->GetSheet(i),static_cast<CDrawMethod *>(pointer)->GetFieldPos(CDrawMethod::Ref),CurrentError++)); theERCListBox.AddString(buffer); } else { refs.insert( ref ); } } ++ it; } } } // Scan netlist to determine the type of each net netCollection::iterator nit = nets->begin(); while (nit != nets->end()) { nodeVector::iterator nv_it = (*nit).second.begin(); int theNetType = nUnknown; CString lastPower = ""; int connections = 0; CDPoint pos; int sheet = 0; while (theNetType < ERR_BASE && nv_it != (*nit).second.end()) { CNetListNode& theNode = *nv_it; CDrawingObject* pObject = theNode.m_parent; if (pObject != NULL) { // Determine the type of this node int node_type = nUnknown; switch (pObject->GetType()) { case xPower: node_type = nPower; if (lastPower=="") { lastPower = static_cast<CDrawPower *>(pObject)->GetValue(); } else { if ( lastPower != static_cast<CDrawPower *>(pObject)->GetValue() ) { theNetType = ERR_POWER; node_type = nUnknown; break; } } connections ++; pos = pObject->m_point_a; sheet = theNode.m_sheet; break; case xNoConnect: node_type = 1; connections ++; pos = pObject->m_point_a; sheet = theNode.m_sheet; break; case xPin: case xPinEx: { CDrawPin *pPin = static_cast<CDrawPin*>( pObject ); switch(pPin->GetElec()) { case 0: // Input node_type = nInput; break; case 1: // Output node_type = nOutput; break; case 2: // Tristate node_type = nBiDir; break; case 3: // Open Collector node_type = nBiDir; break; case 4: // Passive node_type = nPassive; break; case 5: // Input/Output node_type = nBiDir; break; case 6: // Not Connected node_type = nNoConnect; break; } if (pPin->IsPower()) { node_type = nPower; } pos = pPin->GetActivePoint(theNode.m_pMethod); sheet = theNode.m_sheet; connections ++; } break; } theNetType = (node_type!=nUnknown) ? ErcTable[theNetType][node_type] : theNetType; } ++ nv_it; } int ErrorNumber = 0; if (connections == 1) { theNetType = ERR_UNCONNECT; } switch (theNetType) { case nUnknown: if (connections > 0) { ErrorNumber = ERR_UNCONNECTED; } break; case nInput: ErrorNumber = ERR_NOUTPUT; break; case nNoConnect: if (connections > 2) { theNetType = ERR_UNCONNECT; } break; default: ErrorNumber = theNetType; break; } // Is this error to be reported? switch (ErrorNumber) { case ERR_UNCONNECT: if (!((theErrorTest.e).UnConnect)) ErrorNumber = -1; break; case ERR_POWER: if (!((theErrorTest.e).Power)) ErrorNumber = -1; break; case ERR_NOCONNECT: if (!((theErrorTest.e).NoConnect)) ErrorNumber = -1; break; case ERR_NOUTPUT: if (!((theErrorTest.e).NoOutput)) ErrorNumber = -1; break; case ERR_DUPREF: if (!((theErrorTest.e).DupRef)) ErrorNumber = -1; break; case ERR_OUTPUT: if (!((theErrorTest.e).Output)) ErrorNumber = -1; break; case ERR_OUTPUTTOPWR: if (!((theErrorTest.e).OutputPwr)) ErrorNumber = -1; break; case ERR_UNCONNECTED: if (!((theErrorTest.e).UnConnected)) ErrorNumber = -1; break; case ERR_OUTPUTBIDIR: if (!((theErrorTest.e).Output)) ErrorNumber = -1; break; case ERR_POWERBIDIR: if (!((theErrorTest.e).OutputPwr)) ErrorNumber = -1; break; } if (ErrorNumber >= ERR_BASE) { CString buffer; buffer.LoadString( ErrorNumber ); pDoc->GetSheet(sheet-1)->Add(new CDrawError(pDoc->GetSheet(sheet-1),pos,CurrentError++)); theERCListBox.AddString(buffer); } ++ nit; } // Were any errors detected? if (CurrentError == 0) { CString buffer; buffer.LoadString( ERR_NOERROR ); theERCListBox.AddString(buffer); } // Set the normal icon SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW ) ); // Re-Draw the window Invalidate(); }