📄 draw.cpp
字号:
memcpy(s1+strlen(leaf->d.cmp.op1)+2, s, strlen(s));
memcpy(s2+2, leaf->d.cmp.op2, strlen(leaf->d.cmp.op2));
} else {
strcpy(s1, "");
strcpy(s2, TOO_LONG);
}
CenterWithSpaces(*cx, *cy, s1, poweredAfter, FALSE);
CenterWithWires(*cx, *cy, s2, poweredBefore, poweredAfter);
*cx += POS_WIDTH;
break;
}
case ELEM_OPEN:
CenterWithWires(*cx, *cy, "+ +", poweredBefore, poweredAfter);
*cx += POS_WIDTH;
break;
case ELEM_SHORT:
CenterWithWires(*cx, *cy, "+------+", poweredBefore, poweredAfter);
*cx += POS_WIDTH;
break;
case ELEM_ONE_SHOT_RISING:
case ELEM_ONE_SHOT_FALLING: {
char *s1, *s2;
if(which == ELEM_ONE_SHOT_RISING) {
s1 = " _ ";
s2 = "[\x01OSR\x02_/ ]";
} else if(which == ELEM_ONE_SHOT_FALLING) {
s1 = " _ ";
s2 = "[\x01OSF\x02 \\_]";
} else oops();
CenterWithSpaces(*cx, *cy, s1, poweredAfter, FALSE);
CenterWithWires(*cx, *cy, s2, poweredBefore, poweredAfter);
*cx += POS_WIDTH;
break;
}
case ELEM_CTU:
case ELEM_CTD: {
char *s;
if(which == ELEM_CTU)
s = "\x01""CTU\x02";
else if(which == ELEM_CTD)
s = "\x01""CTD\x02";
else oops();
char buf[256];
ElemCounter *c = &leaf->d.counter;
sprintf(buf, "[%s >=%d]", s, c->max);
CenterWithSpaces(*cx, *cy, c->name, poweredAfter, TRUE);
CenterWithWires(*cx, *cy, buf, poweredBefore, poweredAfter);
*cx += POS_WIDTH;
break;
}
case ELEM_RTO:
case ELEM_TON:
case ELEM_TOF: {
char *s;
if(which == ELEM_TON)
s = "\x01TON\x02";
else if(which == ELEM_TOF)
s = "\x01TOF\x02";
else if(which == ELEM_RTO)
s = "\x01RTO\x02";
else oops();
char buf[256];
ElemTimer *t = &leaf->d.timer;
if(t->delay >= 1000*1000) {
sprintf(buf, "[%s %.3f s]", s, t->delay/1000000.0);
} else if(t->delay >= 100*1000) {
sprintf(buf, "[%s %.1f ms]", s, t->delay/1000.0);
} else {
sprintf(buf, "[%s %.2f ms]", s, t->delay/1000.0);
}
CenterWithSpaces(*cx, *cy, t->name, poweredAfter, TRUE);
CenterWithWires(*cx, *cy, buf, poweredBefore, poweredAfter);
*cx += POS_WIDTH;
break;
}
case ELEM_FORMATTED_STRING: {
char bot[100];
sprintf(bot, "{\"%s\"}", leaf->d.fmtdStr.string);
int extra = 2*POS_WIDTH - strlen(leaf->d.fmtdStr.var);
PoweredText(poweredAfter);
NameText();
DrawChars(*cx + (extra/2), *cy + (POS_HEIGHT/2) - 1,
leaf->d.fmtdStr.var);
BodyText();
CenterWithWiresWidth(*cx, *cy, bot, poweredBefore, poweredAfter,
2*POS_WIDTH);
*cx += 2*POS_WIDTH;
break;
}
case ELEM_UART_RECV:
case ELEM_UART_SEND:
CenterWithWires(*cx, *cy,
(which == ELEM_UART_RECV) ? "{UART RECV}" : "{UART SEND}",
poweredBefore, poweredAfter);
CenterWithSpaces(*cx, *cy, leaf->d.uart.name, poweredAfter, TRUE);
*cx += POS_WIDTH;
break;
default:
poweredAfter = DrawEndOfLine(which, leaf, cx, cy, poweredBefore);
break;
}
// And now we can enter the element into the display matrix so that the
// UI routines know what element is at position (gx, gy) when the user
// clicks there, and so that we know where to put the cursor if this
// element is selected.
// Don't use original cx0, as an end of line element might be further
// along than that.
cx0 = *cx - POS_WIDTH;
int gx = cx0/POS_WIDTH;
int gy = cy0/POS_HEIGHT;
if(CheckBoundsUndoIfFails(gx, gy)) return FALSE;
DM_BOUNDS(gx, gy);
DisplayMatrix[gx][gy] = leaf;
DisplayMatrixWhich[gx][gy] = which;
int xadj = 0;
switch(which) {
case ELEM_ADD:
case ELEM_SUB:
case ELEM_MUL:
case ELEM_DIV:
case ELEM_FORMATTED_STRING:
DM_BOUNDS(gx-1, gy);
DisplayMatrix[gx-1][gy] = leaf;
DisplayMatrixWhich[gx-1][gy] = which;
xadj = POS_WIDTH*FONT_WIDTH;
break;
}
if(which == ELEM_COMMENT) {
int i;
for(i = 0; i < ColsAvailable; i++) {
DisplayMatrix[i][gy] = leaf;
DisplayMatrixWhich[i][gy] = ELEM_COMMENT;
}
xadj = (ColsAvailable-1)*POS_WIDTH*FONT_WIDTH;
}
int x0 = X_PADDING + cx0*FONT_WIDTH;
int y0 = Y_PADDING + cy0*FONT_HEIGHT;
if(leaf->selectedState != SELECTED_NONE && leaf == Selected) {
SelectionActive = TRUE;
}
switch(leaf->selectedState) {
case SELECTED_LEFT:
Cursor.left = x0 + FONT_WIDTH - 4 - xadj;
Cursor.top = y0 - FONT_HEIGHT/2;
Cursor.width = 2;
Cursor.height = POS_HEIGHT*FONT_HEIGHT;
break;
case SELECTED_RIGHT:
Cursor.left = x0 + (POS_WIDTH-1)*FONT_WIDTH - 5;
Cursor.top = y0 - FONT_HEIGHT/2;
Cursor.width = 2;
Cursor.height = POS_HEIGHT*FONT_HEIGHT;
break;
case SELECTED_ABOVE:
Cursor.left = x0 + FONT_WIDTH/2 - xadj;
Cursor.top = y0 - 2;
Cursor.width = (POS_WIDTH-2)*FONT_WIDTH + xadj;
Cursor.height = 2;
break;
case SELECTED_BELOW:
Cursor.left = x0 + FONT_WIDTH/2 - xadj;
Cursor.top = y0 + (POS_HEIGHT-1)*FONT_HEIGHT +
FONT_HEIGHT/2 - 2;
Cursor.width = (POS_WIDTH-2)*(FONT_WIDTH) + xadj;
Cursor.height = 2;
break;
default:
break;
}
return poweredAfter;
}
//-----------------------------------------------------------------------------
// Draw a particular subcircuit with its top left corner at *cx and *cy (in
// characters). If it is a leaf element then just print it and return; else
// loop over the elements of the subcircuit and call ourselves recursively.
// At the end updates *cx and *cy.
//
// In simulation mode, returns TRUE the circuit is energized after the given
// element, else FALSE. This is needed to colour all the wires correctly,
// since the colouring indicates whether a wire is energized.
//-----------------------------------------------------------------------------
BOOL DrawElement(int which, void *elem, int *cx, int *cy, BOOL poweredBefore)
{
BOOL poweredAfter;
int cx0 = *cx, cy0 = *cy;
ElemLeaf *leaf = (ElemLeaf *)elem;
SetBkColor(Hdc, InSimulationMode ? HighlightColours.simBg :
HighlightColours.bg);
NormText();
if(elem == Selected && !InSimulationMode) {
EmphText();
ThisHighlighted = TRUE;
} else {
ThisHighlighted = FALSE;
}
switch(which) {
case ELEM_SERIES_SUBCKT: {
int i;
ElemSubcktSeries *s = (ElemSubcktSeries *)elem;
poweredAfter = poweredBefore;
for(i = 0; i < s->count; i++) {
poweredAfter = DrawElement(s->contents[i].which,
s->contents[i].d.any, cx, cy, poweredAfter);
}
break;
}
case ELEM_PARALLEL_SUBCKT: {
int i;
ElemSubcktParallel *p = (ElemSubcktParallel *)elem;
int widthMax = CountWidthOfElement(which, elem, (*cx)/POS_WIDTH);
int heightMax = CountHeightOfElement(which, elem);
poweredAfter = FALSE;
int lowestPowered = -1;
int downBy = 0;
for(i = 0; i < p->count; i++) {
BOOL poweredThis;
poweredThis = DrawElement(p->contents[i].which,
p->contents[i].d.any, cx, cy, poweredBefore);
if(InSimulationMode) {
if(poweredThis) poweredAfter = TRUE;
PoweredText(poweredThis);
}
while((*cx - cx0) < widthMax*POS_WIDTH) {
int gx = *cx/POS_WIDTH;
int gy = *cy/POS_HEIGHT;
if(CheckBoundsUndoIfFails(gx, gy)) return FALSE;
DM_BOUNDS(gx, gy);
DisplayMatrix[gx][gy] = PADDING_IN_DISPLAY_MATRIX;
DisplayMatrixWhich[gx][gy] = ELEM_PADDING;
char buf[256];
int j;
for(j = 0; j < POS_WIDTH; j++) {
buf[j] = '-';
}
buf[j] = '\0';
DrawChars(*cx, *cy + (POS_HEIGHT/2), buf);
*cx += POS_WIDTH;
}
*cx = cx0;
int justDrewHeight = CountHeightOfElement(p->contents[i].which,
p->contents[i].d.any);
*cy += POS_HEIGHT*justDrewHeight;
downBy += justDrewHeight;
if(poweredThis) {
lowestPowered = downBy - 1;
}
}
*cx = cx0 + POS_WIDTH*widthMax;
*cy = cy0;
int j;
BOOL needWire;
if(*cx/POS_WIDTH != ColsAvailable) {
needWire = FALSE;
for(j = heightMax - 1; j >= 1; j--) {
if(j <= lowestPowered) PoweredText(poweredAfter);
if(DisplayMatrix[*cx/POS_WIDTH - 1][*cy/POS_HEIGHT + j]) {
needWire = TRUE;
}
if(needWire) VerticalWire(*cx - 1, *cy + j*POS_HEIGHT);
}
// stupid special case
if(lowestPowered == 0 && InSimulationMode) {
EmphText();
DrawChars(*cx - 1, *cy + (POS_HEIGHT/2), "+");
}
}
PoweredText(poweredBefore);
needWire = FALSE;
for(j = heightMax - 1; j >= 1; j--) {
if(DisplayMatrix[cx0/POS_WIDTH][*cy/POS_HEIGHT + j]) {
needWire = TRUE;
}
if(needWire) VerticalWire(cx0 - 1, *cy + j*POS_HEIGHT);
}
break;
}
default:
poweredAfter = DrawLeaf(which, leaf, cx, cy, poweredBefore);
break;
}
NormText();
return poweredAfter;
}
//-----------------------------------------------------------------------------
// Draw the rung that signals the end of the program. Kind of useless but
// do it anyways, for convention.
//-----------------------------------------------------------------------------
void DrawEndRung(int cx, int cy)
{
int i;
char *str = "[END]";
int lead = (POS_WIDTH - strlen(str))/2;
ThisHighlighted = TRUE;
for(i = 0; i < lead; i++) {
DrawChars(cx + i, cy + (POS_HEIGHT/2), "-");
}
DrawChars(cx + i, cy + (POS_HEIGHT/2), str);
i += strlen(str);
for(; i < ColsAvailable*POS_WIDTH; i++) {
DrawChars(cx + i, cy + (POS_HEIGHT/2), "-");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -