summaryrefslogtreecommitdiff
path: root/ldmicro
diff options
context:
space:
mode:
Diffstat (limited to 'ldmicro')
-rw-r--r--ldmicro/draw.cpp1512
-rw-r--r--ldmicro/draw_outputdev.cpp18
-rw-r--r--ldmicro/includes/ldmicro.h1
-rw-r--r--ldmicro/lib/linuxUI/linuxUI.cpp4
-rw-r--r--ldmicro/lib/linuxUI/linuxUI.h5
-rw-r--r--ldmicro/maincontrols.cpp252
6 files changed, 948 insertions, 844 deletions
diff --git a/ldmicro/draw.cpp b/ldmicro/draw.cpp
index f08e34c..ad70101 100644
--- a/ldmicro/draw.cpp
+++ b/ldmicro/draw.cpp
@@ -49,12 +49,12 @@ BOOL ThisHighlighted;
if((gy) >= DISPLAY_MATRIX_Y_SIZE || (gy) < 0) oops(); \
}
-//-----------------------------------------------------------------------------
-// The display code is the only part of the program that knows how wide a
-// rung will be when it's displayed; so this is the only convenient place to
-// warn the user and undo their changes if they created something too wide.
-// This is not very clean.
-//-----------------------------------------------------------------------------
+// //-----------------------------------------------------------------------------
+// // The display code is the only part of the program that knows how wide a
+// // rung will be when it's displayed; so this is the only convenient place to
+// // warn the user and undo their changes if they created something too wide.
+// // This is not very clean.
+// //-----------------------------------------------------------------------------
// static BOOL CheckBoundsUndoIfFails(int gx, int gy)
// {
// if(gx >= DISPLAY_MATRIX_X_SIZE || gx < 0 ||
@@ -69,12 +69,12 @@ BOOL ThisHighlighted;
// return FALSE;
// }
-//-----------------------------------------------------------------------------
-// Determine the width, in leaf element units, of a particular subcircuit.
-// The width of a leaf is 1, the width of a series circuit is the sum of
-// of the widths of its members, and the width of a parallel circuit is
-// the maximum of the widths of its members.
-//-----------------------------------------------------------------------------
+// //-----------------------------------------------------------------------------
+// // Determine the width, in leaf element units, of a particular subcircuit.
+// // The width of a leaf is 1, the width of a series circuit is the sum of
+// // of the widths of its members, and the width of a parallel circuit is
+// // the maximum of the widths of its members.
+// //-----------------------------------------------------------------------------
// static int CountWidthOfElement(int which, void *elem, int soFar)
// {
// switch(which) {
@@ -181,13 +181,13 @@ BOOL ThisHighlighted;
// }
// }
-//-----------------------------------------------------------------------------
-// Determine the height, in leaf element units, of a particular subcircuit.
-// The height of a leaf is 1, the height of a parallel circuit is the sum of
-// of the heights of its members, and the height of a series circuit is the
-// maximum of the heights of its members. (This is the dual of the width
-// case.)
-//-----------------------------------------------------------------------------
+// //-----------------------------------------------------------------------------
+// // Determine the height, in leaf element units, of a particular subcircuit.
+// // The height of a leaf is 1, the height of a parallel circuit is the sum of
+// // of the heights of its members, and the height of a series circuit is the
+// // maximum of the heights of its members. (This is the dual of the width
+// // case.)
+// //-----------------------------------------------------------------------------
// int CountHeightOfElement(int which, void *elem)
// {
// switch(which) {
@@ -226,10 +226,10 @@ BOOL ThisHighlighted;
// }
// }
-//-----------------------------------------------------------------------------
-// Determine the width, in leaf element units, of the widest row of the PLC
-// program (i.e. loop over all the rungs and find the widest).
-//-----------------------------------------------------------------------------
+// //-----------------------------------------------------------------------------
+// // Determine the width, in leaf element units, of the widest row of the PLC
+// // program (i.e. loop over all the rungs and find the widest).
+// //-----------------------------------------------------------------------------
// int ProgCountWidestRow(void)
// {
// int i;
@@ -246,10 +246,10 @@ BOOL ThisHighlighted;
// return max;
// }
-//-----------------------------------------------------------------------------
-// Draw a vertical wire one leaf element unit high up from (cx, cy), where cx
-// and cy are in charcter units.
-//-----------------------------------------------------------------------------
+// //-----------------------------------------------------------------------------
+// // Draw a vertical wire one leaf element unit high up from (cx, cy), where cx
+// // and cy are in charcter units.
+// //-----------------------------------------------------------------------------
// static void VerticalWire(int cx, int cy)
// {
// int j;
@@ -260,9 +260,9 @@ BOOL ThisHighlighted;
// DrawChars(cx, cy + (POS_HEIGHT/2 - POS_HEIGHT), "+");
// }
-//-----------------------------------------------------------------------------
-// Convenience functions for making the text colors pretty, for DrawElement.
-//-----------------------------------------------------------------------------
+// //-----------------------------------------------------------------------------
+// // Convenience functions for making the text colors pretty, for DrawElement.
+// //-----------------------------------------------------------------------------
// static void NormText(void)
// {
// SetTextColor(Hdc, InSimulationMode ? HighlightColours.simOff :
@@ -301,11 +301,11 @@ BOOL ThisHighlighted;
// }
// }
-//-----------------------------------------------------------------------------
-// Count the length of a string, in characters. Nonstandard because the
-// string may contain special characters to indicate formatting (syntax
-// highlighting).
-//-----------------------------------------------------------------------------
+// //-----------------------------------------------------------------------------
+// // Count the length of a string, in characters. Nonstandard because the
+// // string may contain special characters to indicate formatting (syntax
+// // highlighting).
+// //-----------------------------------------------------------------------------
// static int FormattedStrlen(char *str)
// {
// int l = 0;
@@ -318,10 +318,10 @@ BOOL ThisHighlighted;
// return l;
// }
-//-----------------------------------------------------------------------------
-// Draw a string, centred in the space of a single position, with spaces on
-// the left and right. Draws on the upper line of the position.
-//-----------------------------------------------------------------------------
+// //-----------------------------------------------------------------------------
+// // Draw a string, centred in the space of a single position, with spaces on
+// // the left and right. Draws on the upper line of the position.
+// //-----------------------------------------------------------------------------
// static void CenterWithSpaces(int cx, int cy, char *str, BOOL powered,
// BOOL isName)
// {
@@ -332,10 +332,10 @@ BOOL ThisHighlighted;
// if(isName) BodyText();
// }
-//-----------------------------------------------------------------------------
-// Like CenterWithWires, but for an arbitrary width position (e.g. for ADD
-// and SUB, which are double-width).
-//-----------------------------------------------------------------------------
+// //-----------------------------------------------------------------------------
+// // Like CenterWithWires, but for an arbitrary width position (e.g. for ADD
+// // and SUB, which are double-width).
+// //-----------------------------------------------------------------------------
// static void CenterWithWiresWidth(int cx, int cy, char *str, BOOL before,
// BOOL after, int totalWidth)
// {
@@ -355,716 +355,716 @@ BOOL ThisHighlighted;
// }
// }
-//-----------------------------------------------------------------------------
-// Draw a string, centred in the space of a single position, with en dashes on
-// the left and right coloured according to the powered state. Draws on the
-// middle line.
-//-----------------------------------------------------------------------------
-// static void CenterWithWires(int cx, int cy, char *str, BOOL before, BOOL after)
-// {
-// CenterWithWiresWidth(cx, cy, str, before, after, POS_WIDTH);
-// }
-
-//-----------------------------------------------------------------------------
-// Draw an end of line element (coil, RES, MOV, etc.). Special things about
-// an end of line element: we must right-justify it.
-//-----------------------------------------------------------------------------
-// static BOOL DrawEndOfLine(int which, ElemLeaf *leaf, int *cx, int *cy,
-// BOOL poweredBefore)
-// {
-// int cx0 = *cx, cy0 = *cy;
-
-// BOOL poweredAfter = leaf->poweredAfter;
-
-// int thisWidth;
-// switch(which) {
-// case ELEM_ADD:
-// case ELEM_SUB:
-// case ELEM_MUL:
-// case ELEM_DIV:
-// thisWidth = 2;
-// break;
-
-// default:
-// thisWidth = 1;
-// break;
-// }
-
-// NormText();
-// PoweredText(poweredBefore);
-// while(*cx < (ColsAvailable-thisWidth)*POS_WIDTH) {
-// int gx = *cx/POS_WIDTH;
-// int gy = *cy/POS_HEIGHT;
-
-// if(CheckBoundsUndoIfFails(gx, gy)) return FALSE;
-
-// if(gx >= DISPLAY_MATRIX_X_SIZE) oops();
-// DM_BOUNDS(gx, gy);
-// DisplayMatrix[gx][gy] = PADDING_IN_DISPLAY_MATRIX;
-// DisplayMatrixWhich[gx][gy] = ELEM_PADDING;
-
-// int i;
-// for(i = 0; i < POS_WIDTH; i++) {
-// DrawChars(*cx + i, *cy + (POS_HEIGHT/2), "-");
-// }
-// *cx += POS_WIDTH;
-// cx0 += POS_WIDTH;
-// }
-
-// if(leaf == Selected && !InSimulationMode) {
-// EmphText();
-// ThisHighlighted = TRUE;
-// } else {
-// ThisHighlighted = FALSE;
-// }
-
-// switch(which) {
-// case ELEM_CTC: {
-// char buf[256];
-// ElemCounter *c = &leaf->d.counter;
-// sprintf(buf, "{\x01""CTC\x02 0:%d}", c->max);
-
-// CenterWithSpaces(*cx, *cy, c->name, poweredAfter, TRUE);
-// CenterWithWires(*cx, *cy, buf, poweredBefore, poweredAfter);
-// break;
-// }
-// case ELEM_RES: {
-// ElemReset *r = &leaf->d.reset;
-// CenterWithSpaces(*cx, *cy, r->name, poweredAfter, TRUE);
-// CenterWithWires(*cx, *cy, "{RES}", poweredBefore, poweredAfter);
-// break;
-// }
-// case ELEM_READ_ADC: {
-// ElemReadAdc *r = &leaf->d.readAdc;
-// CenterWithSpaces(*cx, *cy, r->name, poweredAfter, TRUE);
-// CenterWithWires(*cx, *cy, "{READ ADC}", poweredBefore,
-// poweredAfter);
-// break;
-// }
-// case ELEM_SET_PWM: {
-// ElemSetPwm *s = &leaf->d.setPwm;
-// CenterWithSpaces(*cx, *cy, s->name, poweredAfter, TRUE);
-// char l[50];
-// if(s->targetFreq >= 100000) {
-// sprintf(l, "{PWM %d kHz}", (s->targetFreq+500)/1000);
-// } else if(s->targetFreq >= 10000) {
-// sprintf(l, "{PWM %.1f kHz}", s->targetFreq/1000.0);
-// } else if(s->targetFreq >= 1000) {
-// sprintf(l, "{PWM %.2f kHz}", s->targetFreq/1000.0);
-// } else {
-// sprintf(l, "{PWM %d Hz}", s->targetFreq);
-// }
-// CenterWithWires(*cx, *cy, l, poweredBefore,
-// poweredAfter);
-// break;
-// }
-// case ELEM_PERSIST:
-// CenterWithSpaces(*cx, *cy, leaf->d.persist.var, poweredAfter, TRUE);
-// CenterWithWires(*cx, *cy, "{PERSIST}", poweredBefore, poweredAfter);
-// break;
-
-// case ELEM_MOVE: {
-// char top[256];
-// char bot[256];
-// ElemMove *m = &leaf->d.move;
-
-// if((strlen(m->dest) > (POS_WIDTH - 9)) ||
-// (strlen(m->src) > (POS_WIDTH - 9)))
-// {
-// CenterWithWires(*cx, *cy, TOO_LONG, poweredBefore,
-// poweredAfter);
-// break;
-// }
-
-// strcpy(top, "{ }");
-// memcpy(top+1, m->dest, strlen(m->dest));
-// top[strlen(m->dest) + 3] = ':';
-// top[strlen(m->dest) + 4] = '=';
-
-// strcpy(bot, "{ \x01MOV\x02}");
-// memcpy(bot+2, m->src, strlen(m->src));
-
-// CenterWithSpaces(*cx, *cy, top, poweredAfter, FALSE);
-// CenterWithWires(*cx, *cy, bot, poweredBefore, poweredAfter);
-// break;
-// }
-// case ELEM_MASTER_RELAY:
-// CenterWithWires(*cx, *cy, "{MASTER RLY}", poweredBefore,
-// poweredAfter);
-// break;
-
-// case ELEM_SHIFT_REGISTER: {
-// char bot[MAX_NAME_LEN+20];
-// memset(bot, ' ', sizeof(bot));
-// bot[0] = '{';
-// sprintf(bot+2, "%s0..%d", leaf->d.shiftRegister.name,
-// leaf->d.shiftRegister.stages-1);
-// bot[strlen(bot)] = ' ';
-// bot[13] = '}';
-// bot[14] = '\0';
-// CenterWithSpaces(*cx, *cy, "{\x01SHIFT REG\x02 }",
-// poweredAfter, FALSE);
-// CenterWithWires(*cx, *cy, bot, poweredBefore, poweredAfter);
-// break;
-// }
-// case ELEM_PIECEWISE_LINEAR:
-// case ELEM_LOOK_UP_TABLE: {
-// char top[MAX_NAME_LEN+20], bot[MAX_NAME_LEN+20];
-// char *dest, *index, *str;
-// if(which == ELEM_PIECEWISE_LINEAR) {
-// dest = leaf->d.piecewiseLinear.dest;
-// index = leaf->d.piecewiseLinear.index;
-// str = "PWL";
-// } else {
-// dest = leaf->d.lookUpTable.dest;
-// index = leaf->d.lookUpTable.index;
-// str = "LUT";
-// }
-// memset(top, ' ', sizeof(top));
-// top[0] = '{';
-// sprintf(top+2, "%s :=", dest);
-// top[strlen(top)] = ' ';
-// top[13] = '}';
-// top[14] = '\0';
-// CenterWithSpaces(*cx, *cy, top, poweredAfter, FALSE);
-// memset(bot, ' ', sizeof(bot));
-// bot[0] = '{';
-// sprintf(bot+2, " %s[%s]", str, index);
-// bot[strlen(bot)] = ' ';
-// bot[13] = '}';
-// bot[14] = '\0';
-// CenterWithWires(*cx, *cy, bot, poweredBefore, poweredAfter);
-// break;
-// }
-// case ELEM_COIL: {
-// char buf[4];
-// ElemCoil *c = &leaf->d.coil;
-
-// buf[0] = '(';
-// if(c->negated) {
-// buf[1] = '/';
-// } else if(c->setOnly) {
-// buf[1] = 'S';
-// } else if(c->resetOnly) {
-// buf[1] = 'R';
-// } else {
-// buf[1] = ' ';
-// }
-// buf[2] = ')';
-// buf[3] = '\0';
-
-// CenterWithSpaces(*cx, *cy, c->name, poweredAfter, TRUE);
-// CenterWithWires(*cx, *cy, buf, poweredBefore, poweredAfter);
-// break;
-// }
-// case ELEM_DIV:
-// case ELEM_MUL:
-// case ELEM_SUB:
-// case ELEM_ADD: {
-// char top[POS_WIDTH*2-3+2];
-// char bot[POS_WIDTH*2-3];
-
-// memset(top, ' ', sizeof(top)-1);
-// top[0] = '{';
-
-// memset(bot, ' ', sizeof(bot)-1);
-// bot[0] = '{';
-
-// int lt = 1;
-// if(which == ELEM_ADD) {
-// memcpy(top+lt, "\x01""ADD\x02", 5);
-// } else if(which == ELEM_SUB) {
-// memcpy(top+lt, "\x01SUB\x02", 5);
-// } else if(which == ELEM_MUL) {
-// memcpy(top+lt, "\x01MUL\x02", 5);
-// } else if(which == ELEM_DIV) {
-// memcpy(top+lt, "\x01""DIV\x02", 5);
-// } else oops();
-
-// lt += 7;
-// memcpy(top+lt, leaf->d.math.dest, strlen(leaf->d.math.dest));
-// lt += strlen(leaf->d.math.dest) + 2;
-// top[lt++] = ':';
-// top[lt++] = '=';
-
-// int lb = 2;
-// memcpy(bot+lb, leaf->d.math.op1, strlen(leaf->d.math.op1));
-// lb += strlen(leaf->d.math.op1) + 1;
-// if(which == ELEM_ADD) {
-// bot[lb++] = '+';
-// } else if(which == ELEM_SUB) {
-// bot[lb++] = '-';
-// } else if(which == ELEM_MUL) {
-// bot[lb++] = '*';
-// } else if(which == ELEM_DIV) {
-// bot[lb++] = '/';
-// } else oops();
-// lb++;
-// memcpy(bot+lb, leaf->d.math.op2, strlen(leaf->d.math.op2));
-// lb += strlen(leaf->d.math.op2);
-
-// int l = max(lb, lt - 2);
-// top[l+2] = '}'; top[l+3] = '\0';
-// bot[l] = '}'; bot[l+1] = '\0';
-
-// int extra = 2*POS_WIDTH - FormattedStrlen(top);
-// PoweredText(poweredAfter);
-// DrawChars(*cx + (extra/2), *cy + (POS_HEIGHT/2) - 1, top);
-// CenterWithWiresWidth(*cx, *cy, bot, poweredBefore, poweredAfter,
-// 2*POS_WIDTH);
-
-// *cx += POS_WIDTH;
-
-// break;
-// }
-// default:
-// oops();
-// break;
-// }
-
-// *cx += POS_WIDTH;
-
-// return poweredAfter;
-// }
-
-//-----------------------------------------------------------------------------
-// Draw a leaf element. Special things about a leaf: no need to recurse
-// further, and we must put it into the display matrix.
-//-----------------------------------------------------------------------------
-// static BOOL DrawLeaf(int which, ElemLeaf *leaf, int *cx, int *cy,
-// BOOL poweredBefore)
-// {
-// int cx0 = *cx, cy0 = *cy;
-// BOOL poweredAfter = leaf->poweredAfter;
-
-// switch(which) {
-// case ELEM_COMMENT: {
-// char tbuf[MAX_COMMENT_LEN];
-// char tlbuf[MAX_COMMENT_LEN+8];
-
-// strcpy(tbuf, leaf->d.comment.str);
-// char *b = strchr(tbuf, '\n');
-
-// if(b) {
-// if(b[-1] == '\r') b[-1] = '\0';
-// *b = '\0';
-// sprintf(tlbuf, "\x03 ; %s\x02", tbuf);
-// DrawChars(*cx, *cy + (POS_HEIGHT/2) - 1, tlbuf);
-// sprintf(tlbuf, "\x03 ; %s\x02", b+1);
-// DrawChars(*cx, *cy + (POS_HEIGHT/2), tlbuf);
-// } else {
-// sprintf(tlbuf, "\x03 ; %s\x02", tbuf);
-// DrawChars(*cx, *cy + (POS_HEIGHT/2) - 1, tlbuf);
-// }
-
-// *cx += ColsAvailable*POS_WIDTH;
-// break;
-// }
-// case ELEM_PLACEHOLDER: {
-// NormText();
-// CenterWithWiresWidth(*cx, *cy, "--", FALSE, FALSE, 2);
-// *cx += POS_WIDTH;
-// break;
-// }
-// case ELEM_CONTACTS: {
-// char buf[4];
-// ElemContacts *c = &leaf->d.contacts;
-
-// buf[0] = ']';
-// buf[1] = c->negated ? '/' : ' ';
-// buf[2] = '[';
-// buf[3] = '\0';
-
-// CenterWithSpaces(*cx, *cy, c->name, poweredAfter, TRUE);
-// CenterWithWires(*cx, *cy, buf, poweredBefore, poweredAfter);
-
-// *cx += POS_WIDTH;
-// break;
-// }
-// {
-// char *s;
-// case ELEM_EQU:
-// s = "=="; goto cmp;
-// case ELEM_NEQ:
-// s = "/="; goto cmp;
-// case ELEM_GRT:
-// s = ">"; goto cmp;
-// case ELEM_GEQ:
-// s = ">="; goto cmp;
-// case ELEM_LES:
-// s = "<"; goto cmp;
-// case ELEM_LEQ:
-// s = "<="; goto cmp;
-// cmp:
-// char s1[POS_WIDTH+10], s2[POS_WIDTH+10];
-// int l1, l2, lmax;
-
-// l1 = 2 + 1 + strlen(s) + strlen(leaf->d.cmp.op1);
-// l2 = 2 + 1 + strlen(leaf->d.cmp.op2);
-// lmax = max(l1, l2);
-
-// if(lmax < POS_WIDTH) {
-// memset(s1, ' ', sizeof(s1));
-// s1[0] = '[';
-// s1[lmax-1] = ']';
-// s1[lmax] = '\0';
-// strcpy(s2, s1);
-// memcpy(s1+1, leaf->d.cmp.op1, strlen(leaf->d.cmp.op1));
-// 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: {
-// // Careful, string could be longer than fits in our space.
-// char str[POS_WIDTH*2];
-// memset(str, 0, sizeof(str));
-// char *srcStr = leaf->d.fmtdStr.string;
-// memcpy(str, srcStr, min(strlen(srcStr), POS_WIDTH*2 - 7));
-
-// char bot[100];
-// sprintf(bot, "{\"%s\"}", str);
-
-// 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), "-");
-// }
-// }
+// //-----------------------------------------------------------------------------
+// // Draw a string, centred in the space of a single position, with en dashes on
+// // the left and right coloured according to the powered state. Draws on the
+// // middle line.
+// //-----------------------------------------------------------------------------
+// // static void CenterWithWires(int cx, int cy, char *str, BOOL before, BOOL after)
+// // {
+// // CenterWithWiresWidth(cx, cy, str, before, after, POS_WIDTH);
+// // }
+
+// //-----------------------------------------------------------------------------
+// // Draw an end of line element (coil, RES, MOV, etc.). Special things about
+// // an end of line element: we must right-justify it.
+// //-----------------------------------------------------------------------------
+// // static BOOL DrawEndOfLine(int which, ElemLeaf *leaf, int *cx, int *cy,
+// // BOOL poweredBefore)
+// // {
+// // int cx0 = *cx, cy0 = *cy;
+
+// // BOOL poweredAfter = leaf->poweredAfter;
+
+// // int thisWidth;
+// // switch(which) {
+// // case ELEM_ADD:
+// // case ELEM_SUB:
+// // case ELEM_MUL:
+// // case ELEM_DIV:
+// // thisWidth = 2;
+// // break;
+
+// // default:
+// // thisWidth = 1;
+// // break;
+// // }
+
+// // NormText();
+// // PoweredText(poweredBefore);
+// // while(*cx < (ColsAvailable-thisWidth)*POS_WIDTH) {
+// // int gx = *cx/POS_WIDTH;
+// // int gy = *cy/POS_HEIGHT;
+
+// // if(CheckBoundsUndoIfFails(gx, gy)) return FALSE;
+
+// // if(gx >= DISPLAY_MATRIX_X_SIZE) oops();
+// // DM_BOUNDS(gx, gy);
+// // DisplayMatrix[gx][gy] = PADDING_IN_DISPLAY_MATRIX;
+// // DisplayMatrixWhich[gx][gy] = ELEM_PADDING;
+
+// // int i;
+// // for(i = 0; i < POS_WIDTH; i++) {
+// // DrawChars(*cx + i, *cy + (POS_HEIGHT/2), "-");
+// // }
+// // *cx += POS_WIDTH;
+// // cx0 += POS_WIDTH;
+// // }
+
+// // if(leaf == Selected && !InSimulationMode) {
+// // EmphText();
+// // ThisHighlighted = TRUE;
+// // } else {
+// // ThisHighlighted = FALSE;
+// // }
+
+// // switch(which) {
+// // case ELEM_CTC: {
+// // char buf[256];
+// // ElemCounter *c = &leaf->d.counter;
+// // sprintf(buf, "{\x01""CTC\x02 0:%d}", c->max);
+
+// // CenterWithSpaces(*cx, *cy, c->name, poweredAfter, TRUE);
+// // CenterWithWires(*cx, *cy, buf, poweredBefore, poweredAfter);
+// // break;
+// // }
+// // case ELEM_RES: {
+// // ElemReset *r = &leaf->d.reset;
+// // CenterWithSpaces(*cx, *cy, r->name, poweredAfter, TRUE);
+// // CenterWithWires(*cx, *cy, "{RES}", poweredBefore, poweredAfter);
+// // break;
+// // }
+// // case ELEM_READ_ADC: {
+// // ElemReadAdc *r = &leaf->d.readAdc;
+// // CenterWithSpaces(*cx, *cy, r->name, poweredAfter, TRUE);
+// // CenterWithWires(*cx, *cy, "{READ ADC}", poweredBefore,
+// // poweredAfter);
+// // break;
+// // }
+// // case ELEM_SET_PWM: {
+// // ElemSetPwm *s = &leaf->d.setPwm;
+// // CenterWithSpaces(*cx, *cy, s->name, poweredAfter, TRUE);
+// // char l[50];
+// // if(s->targetFreq >= 100000) {
+// // sprintf(l, "{PWM %d kHz}", (s->targetFreq+500)/1000);
+// // } else if(s->targetFreq >= 10000) {
+// // sprintf(l, "{PWM %.1f kHz}", s->targetFreq/1000.0);
+// // } else if(s->targetFreq >= 1000) {
+// // sprintf(l, "{PWM %.2f kHz}", s->targetFreq/1000.0);
+// // } else {
+// // sprintf(l, "{PWM %d Hz}", s->targetFreq);
+// // }
+// // CenterWithWires(*cx, *cy, l, poweredBefore,
+// // poweredAfter);
+// // break;
+// // }
+// // case ELEM_PERSIST:
+// // CenterWithSpaces(*cx, *cy, leaf->d.persist.var, poweredAfter, TRUE);
+// // CenterWithWires(*cx, *cy, "{PERSIST}", poweredBefore, poweredAfter);
+// // break;
+
+// // case ELEM_MOVE: {
+// // char top[256];
+// // char bot[256];
+// // ElemMove *m = &leaf->d.move;
+
+// // if((strlen(m->dest) > (POS_WIDTH - 9)) ||
+// // (strlen(m->src) > (POS_WIDTH - 9)))
+// // {
+// // CenterWithWires(*cx, *cy, TOO_LONG, poweredBefore,
+// // poweredAfter);
+// // break;
+// // }
+
+// // strcpy(top, "{ }");
+// // memcpy(top+1, m->dest, strlen(m->dest));
+// // top[strlen(m->dest) + 3] = ':';
+// // top[strlen(m->dest) + 4] = '=';
+
+// // strcpy(bot, "{ \x01MOV\x02}");
+// // memcpy(bot+2, m->src, strlen(m->src));
+
+// // CenterWithSpaces(*cx, *cy, top, poweredAfter, FALSE);
+// // CenterWithWires(*cx, *cy, bot, poweredBefore, poweredAfter);
+// // break;
+// // }
+// // case ELEM_MASTER_RELAY:
+// // CenterWithWires(*cx, *cy, "{MASTER RLY}", poweredBefore,
+// // poweredAfter);
+// // break;
+
+// // case ELEM_SHIFT_REGISTER: {
+// // char bot[MAX_NAME_LEN+20];
+// // memset(bot, ' ', sizeof(bot));
+// // bot[0] = '{';
+// // sprintf(bot+2, "%s0..%d", leaf->d.shiftRegister.name,
+// // leaf->d.shiftRegister.stages-1);
+// // bot[strlen(bot)] = ' ';
+// // bot[13] = '}';
+// // bot[14] = '\0';
+// // CenterWithSpaces(*cx, *cy, "{\x01SHIFT REG\x02 }",
+// // poweredAfter, FALSE);
+// // CenterWithWires(*cx, *cy, bot, poweredBefore, poweredAfter);
+// // break;
+// // }
+// // case ELEM_PIECEWISE_LINEAR:
+// // case ELEM_LOOK_UP_TABLE: {
+// // char top[MAX_NAME_LEN+20], bot[MAX_NAME_LEN+20];
+// // char *dest, *index, *str;
+// // if(which == ELEM_PIECEWISE_LINEAR) {
+// // dest = leaf->d.piecewiseLinear.dest;
+// // index = leaf->d.piecewiseLinear.index;
+// // str = "PWL";
+// // } else {
+// // dest = leaf->d.lookUpTable.dest;
+// // index = leaf->d.lookUpTable.index;
+// // str = "LUT";
+// // }
+// // memset(top, ' ', sizeof(top));
+// // top[0] = '{';
+// // sprintf(top+2, "%s :=", dest);
+// // top[strlen(top)] = ' ';
+// // top[13] = '}';
+// // top[14] = '\0';
+// // CenterWithSpaces(*cx, *cy, top, poweredAfter, FALSE);
+// // memset(bot, ' ', sizeof(bot));
+// // bot[0] = '{';
+// // sprintf(bot+2, " %s[%s]", str, index);
+// // bot[strlen(bot)] = ' ';
+// // bot[13] = '}';
+// // bot[14] = '\0';
+// // CenterWithWires(*cx, *cy, bot, poweredBefore, poweredAfter);
+// // break;
+// // }
+// // case ELEM_COIL: {
+// // char buf[4];
+// // ElemCoil *c = &leaf->d.coil;
+
+// // buf[0] = '(';
+// // if(c->negated) {
+// // buf[1] = '/';
+// // } else if(c->setOnly) {
+// // buf[1] = 'S';
+// // } else if(c->resetOnly) {
+// // buf[1] = 'R';
+// // } else {
+// // buf[1] = ' ';
+// // }
+// // buf[2] = ')';
+// // buf[3] = '\0';
+
+// // CenterWithSpaces(*cx, *cy, c->name, poweredAfter, TRUE);
+// // CenterWithWires(*cx, *cy, buf, poweredBefore, poweredAfter);
+// // break;
+// // }
+// // case ELEM_DIV:
+// // case ELEM_MUL:
+// // case ELEM_SUB:
+// // case ELEM_ADD: {
+// // char top[POS_WIDTH*2-3+2];
+// // char bot[POS_WIDTH*2-3];
+
+// // memset(top, ' ', sizeof(top)-1);
+// // top[0] = '{';
+
+// // memset(bot, ' ', sizeof(bot)-1);
+// // bot[0] = '{';
+
+// // int lt = 1;
+// // if(which == ELEM_ADD) {
+// // memcpy(top+lt, "\x01""ADD\x02", 5);
+// // } else if(which == ELEM_SUB) {
+// // memcpy(top+lt, "\x01SUB\x02", 5);
+// // } else if(which == ELEM_MUL) {
+// // memcpy(top+lt, "\x01MUL\x02", 5);
+// // } else if(which == ELEM_DIV) {
+// // memcpy(top+lt, "\x01""DIV\x02", 5);
+// // } else oops();
+
+// // lt += 7;
+// // memcpy(top+lt, leaf->d.math.dest, strlen(leaf->d.math.dest));
+// // lt += strlen(leaf->d.math.dest) + 2;
+// // top[lt++] = ':';
+// // top[lt++] = '=';
+
+// // int lb = 2;
+// // memcpy(bot+lb, leaf->d.math.op1, strlen(leaf->d.math.op1));
+// // lb += strlen(leaf->d.math.op1) + 1;
+// // if(which == ELEM_ADD) {
+// // bot[lb++] = '+';
+// // } else if(which == ELEM_SUB) {
+// // bot[lb++] = '-';
+// // } else if(which == ELEM_MUL) {
+// // bot[lb++] = '*';
+// // } else if(which == ELEM_DIV) {
+// // bot[lb++] = '/';
+// // } else oops();
+// // lb++;
+// // memcpy(bot+lb, leaf->d.math.op2, strlen(leaf->d.math.op2));
+// // lb += strlen(leaf->d.math.op2);
+
+// // int l = max(lb, lt - 2);
+// // top[l+2] = '}'; top[l+3] = '\0';
+// // bot[l] = '}'; bot[l+1] = '\0';
+
+// // int extra = 2*POS_WIDTH - FormattedStrlen(top);
+// // PoweredText(poweredAfter);
+// // DrawChars(*cx + (extra/2), *cy + (POS_HEIGHT/2) - 1, top);
+// // CenterWithWiresWidth(*cx, *cy, bot, poweredBefore, poweredAfter,
+// // 2*POS_WIDTH);
+
+// // *cx += POS_WIDTH;
+
+// // break;
+// // }
+// // default:
+// // oops();
+// // break;
+// // }
+
+// // *cx += POS_WIDTH;
+
+// // return poweredAfter;
+// // }
+
+// //-----------------------------------------------------------------------------
+// // Draw a leaf element. Special things about a leaf: no need to recurse
+// // further, and we must put it into the display matrix.
+// //-----------------------------------------------------------------------------
+// // static BOOL DrawLeaf(int which, ElemLeaf *leaf, int *cx, int *cy,
+// // BOOL poweredBefore)
+// // {
+// // int cx0 = *cx, cy0 = *cy;
+// // BOOL poweredAfter = leaf->poweredAfter;
+
+// // switch(which) {
+// // case ELEM_COMMENT: {
+// // char tbuf[MAX_COMMENT_LEN];
+// // char tlbuf[MAX_COMMENT_LEN+8];
+
+// // strcpy(tbuf, leaf->d.comment.str);
+// // char *b = strchr(tbuf, '\n');
+
+// // if(b) {
+// // if(b[-1] == '\r') b[-1] = '\0';
+// // *b = '\0';
+// // sprintf(tlbuf, "\x03 ; %s\x02", tbuf);
+// // DrawChars(*cx, *cy + (POS_HEIGHT/2) - 1, tlbuf);
+// // sprintf(tlbuf, "\x03 ; %s\x02", b+1);
+// // DrawChars(*cx, *cy + (POS_HEIGHT/2), tlbuf);
+// // } else {
+// // sprintf(tlbuf, "\x03 ; %s\x02", tbuf);
+// // DrawChars(*cx, *cy + (POS_HEIGHT/2) - 1, tlbuf);
+// // }
+
+// // *cx += ColsAvailable*POS_WIDTH;
+// // break;
+// // }
+// // case ELEM_PLACEHOLDER: {
+// // NormText();
+// // CenterWithWiresWidth(*cx, *cy, "--", FALSE, FALSE, 2);
+// // *cx += POS_WIDTH;
+// // break;
+// // }
+// // case ELEM_CONTACTS: {
+// // char buf[4];
+// // ElemContacts *c = &leaf->d.contacts;
+
+// // buf[0] = ']';
+// // buf[1] = c->negated ? '/' : ' ';
+// // buf[2] = '[';
+// // buf[3] = '\0';
+
+// // CenterWithSpaces(*cx, *cy, c->name, poweredAfter, TRUE);
+// // CenterWithWires(*cx, *cy, buf, poweredBefore, poweredAfter);
+
+// // *cx += POS_WIDTH;
+// // break;
+// // }
+// // {
+// // char *s;
+// // case ELEM_EQU:
+// // s = "=="; goto cmp;
+// // case ELEM_NEQ:
+// // s = "/="; goto cmp;
+// // case ELEM_GRT:
+// // s = ">"; goto cmp;
+// // case ELEM_GEQ:
+// // s = ">="; goto cmp;
+// // case ELEM_LES:
+// // s = "<"; goto cmp;
+// // case ELEM_LEQ:
+// // s = "<="; goto cmp;
+// // cmp:
+// // char s1[POS_WIDTH+10], s2[POS_WIDTH+10];
+// // int l1, l2, lmax;
+
+// // l1 = 2 + 1 + strlen(s) + strlen(leaf->d.cmp.op1);
+// // l2 = 2 + 1 + strlen(leaf->d.cmp.op2);
+// // lmax = max(l1, l2);
+
+// // if(lmax < POS_WIDTH) {
+// // memset(s1, ' ', sizeof(s1));
+// // s1[0] = '[';
+// // s1[lmax-1] = ']';
+// // s1[lmax] = '\0';
+// // strcpy(s2, s1);
+// // memcpy(s1+1, leaf->d.cmp.op1, strlen(leaf->d.cmp.op1));
+// // 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: {
+// // // Careful, string could be longer than fits in our space.
+// // char str[POS_WIDTH*2];
+// // memset(str, 0, sizeof(str));
+// // char *srcStr = leaf->d.fmtdStr.string;
+// // memcpy(str, srcStr, min(strlen(srcStr), POS_WIDTH*2 - 7));
+
+// // char bot[100];
+// // sprintf(bot, "{\"%s\"}", str);
+
+// // 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), "-");
+// // }
+// // }
diff --git a/ldmicro/draw_outputdev.cpp b/ldmicro/draw_outputdev.cpp
index 5b05db5..e5aeda9 100644
--- a/ldmicro/draw_outputdev.cpp
+++ b/ldmicro/draw_outputdev.cpp
@@ -32,6 +32,7 @@
#include "ldmicro.h"
void (*DrawChars)(int, int, char *);
+GtkSettings *SettingsInstance;
// After an undo all the memory addresses change but make an effort to put
// the cursor roughly where it should be.
@@ -87,22 +88,9 @@ void CALLBACK BlinkCursor(HWND hwnd, UINT msg, UINT_PTR id, DWORD time)
// if(Cursor.left == 0) return;
// PlcCursor c;
- // memcpy(&c, &Cursor, sizeof(c));
+ // SettingsInstance = gtk_settings_get_default();
+ // gtk_settings_install_property_parser (gtk-cursor-blink ,black);
- // c.top -= ScrollYOffset*POS_HEIGHT*FONT_HEIGHT;
- // c.left -= ScrollXOffset;
-
- // if(c.top >= IoListTop) return;
-
- // if(c.top + c.height >= IoListTop) {
- // c.height = IoListTop - c.top - 3;
- // }
-
- // Hdc = GetDC(MainWindow);
- // SelectObject(Hdc, GetStockObject(WHITE_BRUSH));
- // PatBlt(Hdc, c.left, c.top, c.width, c.height, PATINVERT);
- // CursorDrawn = !CursorDrawn;
- // ReleaseDC(MainWindow, Hdc);
}
//-----------------------------------------------------------------------------
diff --git a/ldmicro/includes/ldmicro.h b/ldmicro/includes/ldmicro.h
index 7796a01..64f16c8 100644
--- a/ldmicro/includes/ldmicro.h
+++ b/ldmicro/includes/ldmicro.h
@@ -546,6 +546,7 @@ extern BOOL NeedHoriz;
extern HLIST IoList;
extern int IoListTop;
extern int IoListHeight;
+extern HMENU ScrollWindow;
// draw.cpp
int ProgCountWidestRow(void);
diff --git a/ldmicro/lib/linuxUI/linuxUI.cpp b/ldmicro/lib/linuxUI/linuxUI.cpp
index 907cb35..c20dec1 100644
--- a/ldmicro/lib/linuxUI/linuxUI.cpp
+++ b/ldmicro/lib/linuxUI/linuxUI.cpp
@@ -6,6 +6,10 @@ const UINT MF_GRAYED = 1;
const UINT MF_CHECKED = 2;
const UINT MF_UNCHECKED = 3;
+/// Accelerators (keyboard shortcuts)
+GtkAccelGroup* AccelGroup;
+GClosure* closure;
+
/// ListStore
HWID view;
HTVC column;
diff --git a/ldmicro/lib/linuxUI/linuxUI.h b/ldmicro/lib/linuxUI/linuxUI.h
index 4bd6e71..4ddf164 100644
--- a/ldmicro/lib/linuxUI/linuxUI.h
+++ b/ldmicro/lib/linuxUI/linuxUI.h
@@ -47,6 +47,11 @@ extern const UINT MF_GRAYED;
extern const UINT MF_CHECKED;
extern const UINT MF_UNCHECKED;
+/// Accelerators (keyboard shortcuts)
+extern GtkAccelGroup* AccelGroup;
+extern GClosure* closure;
+
+
/// ListStore
extern GtkWidget *view;
extern GtkTreeViewColumn *column;
diff --git a/ldmicro/maincontrols.cpp b/ldmicro/maincontrols.cpp
index 20cc906..9a3d737 100644
--- a/ldmicro/maincontrols.cpp
+++ b/ldmicro/maincontrols.cpp
@@ -122,7 +122,7 @@ static HMENU TopMenu; // Menu
static HMENU settings;
static HMENU compile;
static HMENU help;
-static HMENU ScrollWindow;
+HMENU ScrollWindow;
// listview used to maintain the list of I/O pins with symbolic names, plus
// the internal relay too
@@ -176,22 +176,36 @@ HMENU MakeMainWindowMenus(void)
compile = gtk_menu_new();
help = gtk_menu_new();
+ // Declaring the accelerator group for keyboard shortcuts
+ AccelGroup = gtk_accel_group_new ();
+ gtk_window_add_accel_group (GTK_WINDOW (MainWindow), AccelGroup);
+
// Creating labels for each menu
- FileLabel = gtk_menu_item_new_with_label("File");
- EditLabel = gtk_menu_item_new_with_label("Edit");
- SettingsLabel = gtk_menu_item_new_with_label("Settings");
- InstructionLabel = gtk_menu_item_new_with_label("Instructions");
- SimulateLabel = gtk_menu_item_new_with_label("Simulate");
- CompileLabel = gtk_menu_item_new_with_label("Compile");
- HelpLabel = gtk_menu_item_new_with_label("Help");
+ FileLabel = gtk_menu_item_new_with_mnemonic("_File");
+ EditLabel = gtk_menu_item_new_with_mnemonic("_Edit");
+ SettingsLabel = gtk_menu_item_new_with_mnemonic("_Settings");
+ InstructionLabel = gtk_menu_item_new_with_mnemonic("_Instructions");
+ SimulateLabel = gtk_menu_item_new_with_mnemonic("_Simulate");
+ CompileLabel = gtk_menu_item_new_with_mnemonic("_Compile");
+ HelpLabel = gtk_menu_item_new_with_mnemonic("_Help");
// Creating labels for File Menu
- MNU_NEW = gtk_menu_item_new_with_label("New");
- MNU_OPEN = gtk_menu_item_new_with_label("Open");
- MNU_SAVE = gtk_menu_item_new_with_label("Save");
- MNU_SAVE_AS = gtk_menu_item_new_with_label("Save As");
- MNU_EXPORT = gtk_menu_item_new_with_label("Export As Text");
- MNU_EXIT = gtk_menu_item_new_with_label("Exit");
+ MNU_NEW = gtk_menu_item_new_with_mnemonic("_New");
+ MNU_OPEN = gtk_menu_item_new_with_mnemonic("_Open");
+ MNU_SAVE = gtk_menu_item_new_with_mnemonic("_Save");
+ MNU_SAVE_AS = gtk_menu_item_new_with_mnemonic("_Save As");
+ MNU_EXPORT = gtk_menu_item_new_with_mnemonic("_Export As Text");
+ MNU_EXIT = gtk_menu_item_new_with_mnemonic("_Exit");
+
+ // Creating keyboard shortcuts for File menu
+ gtk_widget_add_accelerator (MNU_NEW, "activate", AccelGroup, GDK_KEY_N,
+ GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_OPEN, "activate", AccelGroup, GDK_KEY_O,
+ GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_SAVE, "activate", AccelGroup, GDK_KEY_S,
+ GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_EXPORT, "activate", AccelGroup, GDK_KEY_E,
+ GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
// Appending menu items (labels) to File menu and adding separators
gtk_menu_shell_append(GTK_MENU_SHELL (FileMenu), MNU_NEW); // Appending menu items
@@ -206,14 +220,32 @@ HMENU MakeMainWindowMenus(void)
gtk_menu_shell_append(GTK_MENU_SHELL (FileMenu), MNU_EXIT);
// Creating labels for Edit Menu
- MNU_UNDO = gtk_menu_item_new_with_label("Undo");
- MNU_REDO = gtk_menu_item_new_with_label("Redo");
- MNU_INSERT_RUNG_BEFORE = gtk_menu_item_new_with_label("Insert rung Before");
- MNU_INSERT_RUNG_AFTER = gtk_menu_item_new_with_label("Insert Rung After");
- MNU_PUSH_RUNG_UP = gtk_menu_item_new_with_label("Move Selected Rung Up");
- MNU_PUSH_RUNG_DOWN = gtk_menu_item_new_with_label("Move Selected Rung Down");
- MNU_DELETE_ELEMENT = gtk_menu_item_new_with_label("Delete Selected Element");
- MNU_DELETE_RUNG = gtk_menu_item_new_with_label("Delete Rung");
+ MNU_UNDO = gtk_menu_item_new_with_mnemonic("_Undo");
+ MNU_REDO = gtk_menu_item_new_with_mnemonic("_Redo");
+ MNU_INSERT_RUNG_BEFORE = gtk_menu_item_new_with_mnemonic("_Insert rung Before");
+ MNU_INSERT_RUNG_AFTER = gtk_menu_item_new_with_mnemonic("_Insert Rung After");
+ MNU_PUSH_RUNG_UP = gtk_menu_item_new_with_mnemonic("_Move Selected Rung Up");
+ MNU_PUSH_RUNG_DOWN = gtk_menu_item_new_with_mnemonic("_Move Selected Rung Down");
+ MNU_DELETE_ELEMENT = gtk_menu_item_new_with_mnemonic("_Delete Selected Element");
+ MNU_DELETE_RUNG = gtk_menu_item_new_with_mnemonic("_Delete Rung");
+
+ // Creating keyboard shortcuts for Edit menu
+ gtk_widget_add_accelerator (MNU_UNDO, "activate", AccelGroup, GDK_KEY_Z,
+ GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_REDO, "activate", AccelGroup, GDK_KEY_Y,
+ GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_RUNG_BEFORE, "activate", AccelGroup, GDK_KEY_F6,
+ GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_RUNG_AFTER, "activate", AccelGroup, GDK_KEY_V,
+ GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_PUSH_RUNG_UP, "activate", AccelGroup, GDK_KEY_uparrow,
+ GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_PUSH_RUNG_DOWN, "activate", AccelGroup, GDK_KEY_downarrow,
+ GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_DELETE_ELEMENT, "activate", AccelGroup, GDK_KEY_Delete,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_DELETE_RUNG, "activate", AccelGroup, GDK_KEY_Delete,
+ GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
// Appending menu items to Edit menu and adding separators
gtk_menu_shell_append(GTK_MENU_SHELL (EditMenu), MNU_UNDO);
@@ -230,8 +262,8 @@ HMENU MakeMainWindowMenus(void)
gtk_menu_shell_append(GTK_MENU_SHELL (EditMenu), MNU_DELETE_RUNG);
// Creating labels for Settings Menu
- MNU_MCU_SETTINGS = gtk_menu_item_new_with_label ("MCU Parameters...");
- MNU_MICRO_CONTROLLER = gtk_menu_item_new_with_label ("Microcontroller");
+ MNU_MCU_SETTINGS = gtk_menu_item_new_with_mnemonic ("_MCU Parameters...");
+ MNU_MICRO_CONTROLLER = gtk_menu_item_new_with_mnemonic ("_Microcontroller");
// Appending menu items to Settings menu
gtk_menu_shell_append (GTK_MENU_SHELL (settings), MNU_MCU_SETTINGS);
@@ -248,45 +280,101 @@ HMENU MakeMainWindowMenus(void)
gtk_menu_item_set_submenu(GTK_MENU_ITEM(MNU_MICRO_CONTROLLER), ProcessorMenu);
// Creating labels for Instruction Menu and adding separators
- MNU_INSERT_COMMENT = gtk_menu_item_new_with_label("Insert Comment");
- MNU_INSERT_CONTACTS = gtk_menu_item_new_with_label("Insert Contacts");
- MNU_INSERT_OSR = gtk_menu_item_new_with_label("Insert OSR (One Shot Rising)");
- MNU_INSERT_OSF = gtk_menu_item_new_with_label("Insert OSF (One Shot Falling)");
- MNU_INSERT_TON = gtk_menu_item_new_with_label("Insert TON (Delayed Turn On)");
- MNU_INSERT_TOF = gtk_menu_item_new_with_label("Insert TOF (Delayed Turn Off)");
- MNU_INSERT_RTO = gtk_menu_item_new_with_label("Insert RTO (Retentive Delayed Turn On)");
- MNU_INSERT_CTU = gtk_menu_item_new_with_label("Insert CTU (Count Up)");
- MNU_INSERT_CTD = gtk_menu_item_new_with_label("Insert CTD (Count Down)");
- MNU_INSERT_CTC = gtk_menu_item_new_with_label("Insert CTC (Count Circular)");
- MNU_INSERT_EQU = gtk_menu_item_new_with_label("Insert EQU (Compare for Equals)");
- MNU_INSERT_NEQ = gtk_menu_item_new_with_label("Insert NEQ (Compare for Not Equals)");
- MNU_INSERT_GRT = gtk_menu_item_new_with_label("Insert GRT (Compare for Greater Than)");
- MNU_INSERT_GEQ = gtk_menu_item_new_with_label("Insert GEQ (Compare for Greater Than or Equal)");
- MNU_INSERT_LES = gtk_menu_item_new_with_label("Insert LES (Compare for Less Than)");
- MNU_INSERT_LEQ = gtk_menu_item_new_with_label("Insert LEQ (Compare for Less Than or Equal)");
- MNU_INSERT_OPEN = gtk_menu_item_new_with_label("Insert Open Circuit");
- MNU_INSERT_SHORT = gtk_menu_item_new_with_label("Insert Short Circuit");
- MNU_INSERT_MASTER_RLY = gtk_menu_item_new_with_label("Insert Master Control Relay");
- MNU_INSERT_COIL = gtk_menu_item_new_with_label("Insert Coil");
- MNU_INSERT_RES = gtk_menu_item_new_with_label("Insert RES (Counter/RTO Reset)");
- MNU_INSERT_MOV = gtk_menu_item_new_with_label("Insert MOV (Move)");
- MNU_INSERT_ADD = gtk_menu_item_new_with_label("Insert ADD (16-bit Integer Ad)");
- MNU_INSERT_SUB = gtk_menu_item_new_with_label("Insert SUB (16-bit Integer Subtract)");
- MNU_INSERT_MUL = gtk_menu_item_new_with_label("Insert MUL (16-bit Integer Multiply)");
- MNU_INSERT_DIV = gtk_menu_item_new_with_label("Insert DIV (16-bit Integer Division)");
- MNU_INSERT_SHIFT_REG = gtk_menu_item_new_with_label("Insert Shift Register");
- MNU_INSERT_LUT = gtk_menu_item_new_with_label("Insert Look-Up Table");
- MNU_INSERT_PWL = gtk_menu_item_new_with_label("Insert Piecewise Linear");
- MNU_INSERT_FMTD_STR = gtk_menu_item_new_with_label("Insert Formatted String Over UART");
- MNU_INSERT_UART_SEND = gtk_menu_item_new_with_label("Insert UART Send");
- MNU_INSERT_UART_RECV = gtk_menu_item_new_with_label("Insert UART Receive");
- MNU_INSERT_SET_PWM = gtk_menu_item_new_with_label("Insert Set PWM Output");
- MNU_INSERT_READ_ADC = gtk_menu_item_new_with_label("Insert A/D Converter Read");
- MNU_INSERT_PERSIST = gtk_menu_item_new_with_label("Insert Make Persistent");
- MNU_MAKE_NORMAL = gtk_menu_item_new_with_label("Make Normal");
- MNU_NEGATE = gtk_menu_item_new_with_label("Make Negated");
- MNU_MAKE_SET_ONLY = gtk_menu_item_new_with_label("Make Set-Only");
- MNU_MAKE_RESET_ONLY = gtk_menu_item_new_with_label("Make Reset-Only");
+ MNU_INSERT_COMMENT = gtk_menu_item_new_with_mnemonic("_Insert Comment");
+ MNU_INSERT_CONTACTS = gtk_menu_item_new_with_mnemonic("_Insert Contacts");
+ MNU_INSERT_OSR = gtk_menu_item_new_with_mnemonic("_Insert OSR (One Shot Rising)");
+ MNU_INSERT_OSF = gtk_menu_item_new_with_mnemonic("_Insert OSF (One Shot Falling)");
+ MNU_INSERT_TON = gtk_menu_item_new_with_mnemonic("_Insert TON (Delayed Turn On)");
+ MNU_INSERT_TOF = gtk_menu_item_new_with_mnemonic("_Insert TOF (Delayed Turn Off)");
+ MNU_INSERT_RTO = gtk_menu_item_new_with_mnemonic("_Insert RTO (Retentive Delayed Turn On)");
+ MNU_INSERT_CTU = gtk_menu_item_new_with_mnemonic("_Insert CTU (Count Up)");
+ MNU_INSERT_CTD = gtk_menu_item_new_with_mnemonic("_Insert CTD (Count Down)");
+ MNU_INSERT_CTC = gtk_menu_item_new_with_mnemonic("_Insert CTC (Count Circular)");
+ MNU_INSERT_EQU = gtk_menu_item_new_with_mnemonic("_Insert EQU (Compare for Equals)");
+ MNU_INSERT_NEQ = gtk_menu_item_new_with_mnemonic("_Insert NEQ (Compare for Not Equals)");
+ MNU_INSERT_GRT = gtk_menu_item_new_with_mnemonic("_Insert GRT (Compare for Greater Than)");
+ MNU_INSERT_GEQ = gtk_menu_item_new_with_mnemonic("_Insert GEQ (Compare for Greater Than or Equal)");
+ MNU_INSERT_LES = gtk_menu_item_new_with_mnemonic("_Insert LES (Compare for Less Than)");
+ MNU_INSERT_LEQ = gtk_menu_item_new_with_mnemonic("_Insert LEQ (Compare for Less Than or Equal)");
+ MNU_INSERT_OPEN = gtk_menu_item_new_with_mnemonic("_Insert Open Circuit");
+ MNU_INSERT_SHORT = gtk_menu_item_new_with_mnemonic("_Insert Short Circuit");
+ MNU_INSERT_MASTER_RLY = gtk_menu_item_new_with_mnemonic("_Insert Master Control Relay");
+ MNU_INSERT_COIL = gtk_menu_item_new_with_mnemonic("_Insert Coil");
+ MNU_INSERT_RES = gtk_menu_item_new_with_mnemonic("_Insert RES (Counter/RTO Reset)");
+ MNU_INSERT_MOV = gtk_menu_item_new_with_mnemonic("_Insert MOV (Move)");
+ MNU_INSERT_ADD = gtk_menu_item_new_with_mnemonic("_Insert ADD (16-bit Integer Ad)");
+ MNU_INSERT_SUB = gtk_menu_item_new_with_mnemonic("_Insert SUB (16-bit Integer Subtract)");
+ MNU_INSERT_MUL = gtk_menu_item_new_with_mnemonic("_Insert MUL (16-bit Integer Multiply)");
+ MNU_INSERT_DIV = gtk_menu_item_new_with_mnemonic("_Insert DIV (16-bit Integer Division)");
+ MNU_INSERT_SHIFT_REG = gtk_menu_item_new_with_mnemonic("_Insert Shift Register");
+ MNU_INSERT_LUT = gtk_menu_item_new_with_mnemonic("_Insert Look-Up Table");
+ MNU_INSERT_PWL = gtk_menu_item_new_with_mnemonic("_Insert Piecewise Linear");
+ MNU_INSERT_FMTD_STR = gtk_menu_item_new_with_mnemonic("_Insert Formatted String Over UART");
+ MNU_INSERT_UART_SEND = gtk_menu_item_new_with_mnemonic("_Insert UART Send");
+ MNU_INSERT_UART_RECV = gtk_menu_item_new_with_mnemonic("_Insert UART Receive");
+ MNU_INSERT_SET_PWM = gtk_menu_item_new_with_mnemonic("_Insert Set PWM Output");
+ MNU_INSERT_READ_ADC = gtk_menu_item_new_with_mnemonic("_Insert A/D Converter Read");
+ MNU_INSERT_PERSIST = gtk_menu_item_new_with_mnemonic("_Insert Make Persistent");
+ MNU_MAKE_NORMAL = gtk_menu_item_new_with_mnemonic("_Make Normal");
+ MNU_NEGATE = gtk_menu_item_new_with_mnemonic("_Make Negated");
+ MNU_MAKE_SET_ONLY = gtk_menu_item_new_with_mnemonic("_Make Set-Only");
+ MNU_MAKE_RESET_ONLY = gtk_menu_item_new_with_mnemonic("_Make Reset-Only");
+
+ // Creating keyboard shortcuts for Instructions menu
+ gtk_widget_add_accelerator (MNU_INSERT_COMMENT, "activate", AccelGroup, GDK_KEY_semicolon,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_CONTACTS, "activate", AccelGroup, GDK_KEY_C,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_OSR, "activate", AccelGroup, GDK_KEY_backslash,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_OSF, "activate", AccelGroup, GDK_KEY_slash,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_TON, "activate", AccelGroup, GDK_KEY_O,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_TOF, "activate", AccelGroup, GDK_KEY_F,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_RTO, "activate", AccelGroup, GDK_KEY_T,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_CTU, "activate", AccelGroup, GDK_KEY_U,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_CTD, "activate", AccelGroup, GDK_KEY_I,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_CTC, "activate", AccelGroup, GDK_KEY_J,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_EQU, "activate", AccelGroup, GDK_KEY_equal,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_GRT, "activate", AccelGroup, GDK_KEY_greater,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_GEQ, "activate", AccelGroup, GDK_KEY_Stop,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_LES, "activate", AccelGroup, GDK_KEY_less,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_LEQ, "activate", AccelGroup, GDK_KEY_comma,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_COIL, "activate", AccelGroup, GDK_KEY_L,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_RES, "activate", AccelGroup, GDK_KEY_E,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_MOV, "activate", AccelGroup, GDK_KEY_M,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_ADD, "activate", AccelGroup, GDK_KEY_plus,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_SUB, "activate", AccelGroup, GDK_KEY_minus,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_MUL, "activate", AccelGroup, GDK_KEY_multiply,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_DIV, "activate", AccelGroup, GDK_KEY_D,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_INSERT_READ_ADC, "activate", AccelGroup, GDK_KEY_P,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_MAKE_NORMAL, "activate", AccelGroup, GDK_KEY_A,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_NEGATE, "activate", AccelGroup, GDK_KEY_N,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_MAKE_SET_ONLY, "activate", AccelGroup, GDK_KEY_S,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_MAKE_RESET_ONLY, "activate", AccelGroup, GDK_KEY_R,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
// Appending menu items to Instruction menu and adding separators
gtk_menu_shell_append (GTK_MENU_SHELL (InstructionMenu), MNU_INSERT_COMMENT);
@@ -351,27 +439,45 @@ HMENU MakeMainWindowMenus(void)
gtk_menu_shell_append (GTK_MENU_SHELL (InstructionMenu), MNU_MAKE_SET_ONLY);
gtk_menu_shell_append (GTK_MENU_SHELL (InstructionMenu), MNU_MAKE_RESET_ONLY);
- // Creating labels for Simulation Menu
- MNU_COMPILE = gtk_menu_item_new_with_label("Compile");
- MNU_COMPILE_AS = gtk_menu_item_new_with_label("Compile As...");
+ // Creating labels for Compile Menu
+ MNU_COMPILE = gtk_menu_item_new_with_mnemonic("_Compile");
+ MNU_COMPILE_AS = gtk_menu_item_new_with_mnemonic("_Compile As...");
+
+ // Creating keyboard shortcuts for Compile menu
+ gtk_widget_add_accelerator (MNU_COMPILE, "activate", AccelGroup, GDK_KEY_F5,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
// Appending menu items to Compile menu
gtk_menu_shell_append(GTK_MENU_SHELL (compile), MNU_COMPILE);
gtk_menu_shell_append(GTK_MENU_SHELL (compile), MNU_COMPILE_AS);
- // Creating labels for Simulation Menu
- MNU_MANUAL = gtk_menu_item_new_with_label("Manual...");
- MNU_ABOUT = gtk_menu_item_new_with_label("About...");
+ // Creating labels for Help Menu
+ MNU_MANUAL = gtk_menu_item_new_with_mnemonic("_Manual...");
+ MNU_ABOUT = gtk_menu_item_new_with_mnemonic("_About...");
+
+ // Creating keyboard shortcuts for Help menu
+ gtk_widget_add_accelerator (MNU_MANUAL, "activate", AccelGroup, GDK_KEY_F1,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
// Appending menu items to Help menu
gtk_menu_shell_append(GTK_MENU_SHELL (help), MNU_MANUAL);
gtk_menu_shell_append(GTK_MENU_SHELL (help), MNU_ABOUT);
// Creating labels for Simulation Menu
- MNU_SIMULATION_MODE = gtk_check_menu_item_new_with_label("Simulation Mode");
- MNU_START_SIMULATION = gtk_menu_item_new_with_label("Start Real-Time Simulation");
- MNU_STOP_SIMULATION = gtk_menu_item_new_with_label("Halt Simulation");
- MNU_SINGLE_CYCLE = gtk_menu_item_new_with_label("Single Cycle");
+ MNU_SIMULATION_MODE = gtk_check_menu_item_new_with_mnemonic("_Simulation Mode");
+ MNU_START_SIMULATION = gtk_menu_item_new_with_mnemonic("_Start Real-Time Simulation");
+ MNU_STOP_SIMULATION = gtk_menu_item_new_with_mnemonic("_Halt Simulation");
+ MNU_SINGLE_CYCLE = gtk_menu_item_new_with_mnemonic("_Single Cycle");
+
+ // Creating keyboard shortcuts for Edit menu
+ gtk_widget_add_accelerator (MNU_SIMULATION_MODE, "activate", AccelGroup, GDK_KEY_M,
+ GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_START_SIMULATION, "activate", AccelGroup, GDK_KEY_R,
+ GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_STOP_SIMULATION, "activate", AccelGroup, GDK_KEY_H,
+ GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (MNU_SINGLE_CYCLE, "activate", AccelGroup, GDK_KEY_space,
+ GDK_RELEASE_MASK, GTK_ACCEL_VISIBLE);
// Appending menu items to Simulate menu and adding separators
gtk_menu_shell_append(GTK_MENU_SHELL (SimulateMenu), MNU_SIMULATION_MODE);