diff options
Diffstat (limited to 'ldmicro')
-rw-r--r-- | ldmicro/draw.cpp | 1512 | ||||
-rw-r--r-- | ldmicro/draw_outputdev.cpp | 18 | ||||
-rw-r--r-- | ldmicro/includes/ldmicro.h | 1 | ||||
-rw-r--r-- | ldmicro/lib/linuxUI/linuxUI.cpp | 4 | ||||
-rw-r--r-- | ldmicro/lib/linuxUI/linuxUI.h | 5 | ||||
-rw-r--r-- | ldmicro/maincontrols.cpp | 252 |
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); |