📄 circuit.cpp
字号:
//-----------------------------------------------------------------------------
// Copyright 2007 Jonathan Westhues
//
// This file is part of LDmicro.
//
// LDmicro 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 3 of the License, or
// (at your option) any later version.
//
// LDmicro 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 LDmicro. If not, see <http://www.gnu.org/licenses/>.
//------
//
// Routines for modifying the circuit: add a particular element at a
// particular point, delete the selected element, etc.
// Jonathan Westhues, Oct 2004
//-----------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "ldmicro.h"
static ElemSubcktSeries *LoadSeriesFromFile(FILE *f);
//-----------------------------------------------------------------------------
// Convenience routines for allocating frequently-used data structures.
//-----------------------------------------------------------------------------
ElemLeaf *AllocLeaf(void)
{
return (ElemLeaf *)CheckMalloc(sizeof(ElemLeaf));
}
ElemSubcktSeries *AllocSubcktSeries(void)
{
return (ElemSubcktSeries *)CheckMalloc(sizeof(ElemSubcktSeries));
}
ElemSubcktParallel *AllocSubcktParallel(void)
{
return (ElemSubcktParallel *)CheckMalloc(sizeof(ElemSubcktParallel));
}
//-----------------------------------------------------------------------------
// Routine that does the actual work of adding a leaf element to the left/
// right of or above/below the selected element. If we are adding left/right
// in a series circuit then it's easy; just increase length of that
// subcircuit and stick it in. Same goes for above/below in a parallel
// subcircuit. If we are adding above/below in a series circuit or left/right
// in a parallel circuit then we must create a new parallel (for series) or
// series (for parallel) subcircuit with 2 elements, one for the previously
// selected element and one for the new element. Calls itself recursively on
// all subcircuits. Returns TRUE if it or a child made the addition.
//-----------------------------------------------------------------------------
static BOOL AddLeafWorker(int which, void *any, int newWhich, ElemLeaf *newElem)
{
int i;
switch(which) {
case ELEM_SERIES_SUBCKT: {
ElemSubcktSeries *s = (ElemSubcktSeries *)any;
for(i = 0; i < s->count; i++) {
if(s->contents[i].d.any == Selected) {
break;
}
if(s->contents[i].which == ELEM_PARALLEL_SUBCKT) {
if(AddLeafWorker(ELEM_PARALLEL_SUBCKT, s->contents[i].d.any,
newWhich, newElem))
{
return TRUE;
}
}
}
if(i == s->count) break;
if(s->contents[i].which == ELEM_PLACEHOLDER) {
// Special case--placeholders are replaced. They only appear
// in the empty series subcircuit that I generate for them,
// so there is no need to consider them anywhere but here.
// If we copy instead of replacing then the DisplayMatrix
// tables don't get all messed up.
memcpy(s->contents[i].d.leaf, newElem, sizeof(ElemLeaf));
s->contents[i].d.leaf->selectedState = SELECTED_LEFT;
CheckFree(newElem);
s->contents[i].which = newWhich;
SelectedWhich = newWhich;
return TRUE;
}
if(s->count >= (MAX_ELEMENTS_IN_SUBCKT-1)) {
Error(_("Too many elements in subcircuit!"));
return TRUE;
}
switch(Selected->selectedState) {
case SELECTED_LEFT:
memmove(&s->contents[i+1], &s->contents[i],
(s->count - i)*sizeof(s->contents[0]));
s->contents[i].d.leaf = newElem;
s->contents[i].which = newWhich;
(s->count)++;
break;
case SELECTED_RIGHT:
memmove(&s->contents[i+2], &s->contents[i+1],
(s->count - i - 1)*sizeof(s->contents[0]));
s->contents[i+1].d.leaf = newElem;
s->contents[i+1].which = newWhich;
(s->count)++;
break;
case SELECTED_BELOW:
case SELECTED_ABOVE: {
ElemSubcktParallel *p = AllocSubcktParallel();
p->count = 2;
int t;
t = (Selected->selectedState == SELECTED_ABOVE) ? 0 : 1;
p->contents[t].which = newWhich;
p->contents[t].d.leaf = newElem;
t = (Selected->selectedState == SELECTED_ABOVE) ? 1 : 0;
p->contents[t].which = s->contents[i].which;
p->contents[t].d.any = s->contents[i].d.any;
s->contents[i].which = ELEM_PARALLEL_SUBCKT;
s->contents[i].d.parallel = p;
break;
}
default:
oops();
break;
}
return TRUE;
break;
}
case ELEM_PARALLEL_SUBCKT: {
ElemSubcktParallel *p = (ElemSubcktParallel *)any;
for(i = 0; i < p->count; i++) {
if(p->contents[i].d.any == Selected) {
break;
}
if(p->contents[i].which == ELEM_SERIES_SUBCKT) {
if(AddLeafWorker(ELEM_SERIES_SUBCKT, p->contents[i].d.any,
newWhich, newElem))
{
return TRUE;
}
}
}
if(i == p->count) break;
if(p->count >= (MAX_ELEMENTS_IN_SUBCKT-1)) {
Error(_("Too many elements in subcircuit!"));
return TRUE;
}
switch(Selected->selectedState) {
case SELECTED_ABOVE:
memmove(&p->contents[i+1], &p->contents[i],
(p->count - i)*sizeof(p->contents[0]));
p->contents[i].d.leaf = newElem;
p->contents[i].which = newWhich;
(p->count)++;
break;
case SELECTED_BELOW:
memmove(&p->contents[i+2], &p->contents[i+1],
(p->count - i - 1)*sizeof(p->contents[0]));
p->contents[i+1].d.leaf = newElem;
p->contents[i+1].which = newWhich;
(p->count)++;
break;
case SELECTED_LEFT:
case SELECTED_RIGHT: {
ElemSubcktSeries *s = AllocSubcktSeries();
s->count = 2;
int t;
t = (Selected->selectedState == SELECTED_LEFT) ? 0 : 1;
s->contents[t].which = newWhich;
s->contents[t].d.leaf = newElem;
t = (Selected->selectedState == SELECTED_LEFT) ? 1 : 0;
s->contents[t].which = p->contents[i].which;
s->contents[t].d.any = p->contents[i].d.any;
p->contents[i].which = ELEM_SERIES_SUBCKT;
p->contents[i].d.series = s;
break;
}
default:
oops();
break;
}
return TRUE;
break;
}
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Add the specified leaf node in the position indicated by the cursor. We
// will search through the entire program using AddLeafWorker to find the
// insertion point, and AddLeafWorker will stick it in at the requested
// location and return TRUE. We return TRUE if it worked, else FALSE.
//-----------------------------------------------------------------------------
static BOOL AddLeaf(int newWhich, ElemLeaf *newElem)
{
if(!Selected || Selected->selectedState == SELECTED_NONE) return FALSE;
int i;
for(i = 0; i < Prog.numRungs; i++) {
if(AddLeafWorker(ELEM_SERIES_SUBCKT, Prog.rungs[i], newWhich, newElem))
{
WhatCanWeDoFromCursorAndTopology();
return TRUE;
}
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Routines to allocate memory for a new circuit element (contact, coil, etc.)
// and insert it into the current program with AddLeaf. Fill in some default
// parameters, name etc. when we create the leaf; user can change them later.
//-----------------------------------------------------------------------------
void AddComment(char *str)
{
if(!CanInsertComment) return;
ElemLeaf *c = AllocLeaf();
strcpy(c->d.comment.str, str);
AddLeaf(ELEM_COMMENT, c);
}
void AddContact(void)
{
if(!CanInsertOther) return;
ElemLeaf *c = AllocLeaf();
strcpy(c->d.contacts.name, "Xnew");
c->d.contacts.negated = FALSE;
AddLeaf(ELEM_CONTACTS, c);
}
void AddCoil(void)
{
if(!CanInsertEnd) return;
ElemLeaf *c = AllocLeaf();
strcpy(c->d.coil.name, "Ynew");
c->d.coil.negated = FALSE;
c->d.coil.setOnly = FALSE;
c->d.coil.resetOnly = FALSE;
AddLeaf(ELEM_COIL, c);
}
void AddTimer(int which)
{
if(!CanInsertOther) return;
ElemLeaf *t = AllocLeaf();
strcpy(t->d.timer.name, "Tnew");
t->d.timer.delay = 100000;
AddLeaf(which, t);
}
void AddEmpty(int which)
{
if(!CanInsertOther) return;
ElemLeaf *t = AllocLeaf();
AddLeaf(which, t);
}
void AddReset(void)
{
if(!CanInsertEnd) return;
ElemLeaf *t = AllocLeaf();
strcpy(t->d.reset.name, "Tnew");
AddLeaf(ELEM_RES, t);
}
void AddMasterRelay(void)
{
if(!CanInsertEnd) return;
ElemLeaf *t = AllocLeaf();
AddLeaf(ELEM_MASTER_RELAY, t);
}
void AddShiftRegister(void)
{
if(!CanInsertEnd) return;
ElemLeaf *t = AllocLeaf();
strcpy(t->d.shiftRegister.name, "reg");
t->d.shiftRegister.stages = 7;
AddLeaf(ELEM_SHIFT_REGISTER, t);
}
void AddFormattedString(void)
{
if(!CanInsertOther) return;
ElemLeaf *t = AllocLeaf();
strcpy(t->d.fmtdStr.var, "var");
strcpy(t->d.fmtdStr.string, "value: \\3\\r\\n");
AddLeaf(ELEM_FORMATTED_STRING, t);
}
void AddLookUpTable(void)
{
if(!CanInsertEnd) return;
ElemLeaf *t = AllocLeaf();
strcpy(t->d.lookUpTable.dest, "dest");
strcpy(t->d.lookUpTable.index, "index");
t->d.lookUpTable.count = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -