summaryrefslogtreecommitdiff
path: root/ldmicro/simulate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ldmicro/simulate.cpp')
-rw-r--r--ldmicro/simulate.cpp1420
1 files changed, 718 insertions, 702 deletions
diff --git a/ldmicro/simulate.cpp b/ldmicro/simulate.cpp
index ecb9b0e..0b3c206 100644
--- a/ldmicro/simulate.cpp
+++ b/ldmicro/simulate.cpp
@@ -89,8 +89,8 @@ static int IntPc;
// A window to allow simulation with the UART stuff (insert keystrokes into
// the program, view the output, like a terminal window).
-static HWND UartSimulationWindow;
-static HWND UartSimulationTextControl;
+static HWID UartSimulationWindow;
+static HWID UartSimulationTextControl;
static LONG_PTR PrevTextProc;
static int QueuedUartCharacter = -1;
@@ -106,117 +106,117 @@ static char *MarkUsedVariable(char *name, DWORD flag);
// Looks in the SingleBitItems list; if an item is not present then it is
// FALSE by default.
//-----------------------------------------------------------------------------
-// static BOOL SingleBitOn(char *name)
-// {
-// int i;
-// for(i = 0; i < SingleBitItemsCount; i++) {
-// if(strcmp(SingleBitItems[i].name, name)==0) {
-// return SingleBitItems[i].powered;
-// }
-// }
-// return FALSE;
-// }
+static BOOL SingleBitOn(char *name)
+{
+ int i;
+ for(i = 0; i < SingleBitItemsCount; i++) {
+ if(strcmp(SingleBitItems[i].name, name)==0) {
+ return SingleBitItems[i].powered;
+ }
+ }
+ return FALSE;
+}
//-----------------------------------------------------------------------------
// Set the state of a single-bit item. Adds it to the list if it is not there
// already.
//-----------------------------------------------------------------------------
-// static void SetSingleBit(char *name, BOOL state)
-// {
-// int i;
-// for(i = 0; i < SingleBitItemsCount; i++) {
-// if(strcmp(SingleBitItems[i].name, name)==0) {
-// SingleBitItems[i].powered = state;
-// return;
-// }
-// }
-// if(i < MAX_IO) {
-// strcpy(SingleBitItems[i].name, name);
-// SingleBitItems[i].powered = state;
-// SingleBitItemsCount++;
-// }
-// }
+static void SetSingleBit(char *name, BOOL state)
+{
+ int i;
+ for(i = 0; i < SingleBitItemsCount; i++) {
+ if(strcmp(SingleBitItems[i].name, name)==0) {
+ SingleBitItems[i].powered = state;
+ return;
+ }
+ }
+ if(i < MAX_IO) {
+ strcpy(SingleBitItems[i].name, name);
+ SingleBitItems[i].powered = state;
+ SingleBitItemsCount++;
+ }
+}
//-----------------------------------------------------------------------------
// Count a timer up (i.e. increment its associated count by 1). Must already
// exist in the table.
//-----------------------------------------------------------------------------
-// static void IncrementVariable(char *name)
-// {
-// int i;
-// for(i = 0; i < VariablesCount; i++) {
-// if(strcmp(Variables[i].name, name)==0) {
-// (Variables[i].val)++;
-// return;
-// }
-// }
-// oops();
-// }
+static void IncrementVariable(char *name)
+{
+ int i;
+ for(i = 0; i < VariablesCount; i++) {
+ if(strcmp(Variables[i].name, name)==0) {
+ (Variables[i].val)++;
+ return;
+ }
+ }
+ oops();
+}
//-----------------------------------------------------------------------------
// Set a variable to a value.
//-----------------------------------------------------------------------------
-// static void SetSimulationVariable(char *name, SWORD val)
-// {
-// int i;
-// for(i = 0; i < VariablesCount; i++) {
-// if(strcmp(Variables[i].name, name)==0) {
-// Variables[i].val = val;
-// return;
-// }
-// }
-// MarkUsedVariable(name, VAR_FLAG_OTHERWISE_FORGOTTEN);
-// SetSimulationVariable(name, val);
-// }
+static void SetSimulationVariable(char *name, SWORD val)
+{
+ int i;
+ for(i = 0; i < VariablesCount; i++) {
+ if(strcmp(Variables[i].name, name)==0) {
+ Variables[i].val = val;
+ return;
+ }
+ }
+ MarkUsedVariable(name, VAR_FLAG_OTHERWISE_FORGOTTEN);
+ SetSimulationVariable(name, val);
+}
//-----------------------------------------------------------------------------
// Read a variable's value.
//-----------------------------------------------------------------------------
-// SWORD GetSimulationVariable(char *name)
-// {
-// int i;
-// for(i = 0; i < VariablesCount; i++) {
-// if(strcmp(Variables[i].name, name)==0) {
-// return Variables[i].val;
-// }
-// }
-// MarkUsedVariable(name, VAR_FLAG_OTHERWISE_FORGOTTEN);
-// return GetSimulationVariable(name);
-// }
+SWORD GetSimulationVariable(char *name)
+{
+ int i;
+ for(i = 0; i < VariablesCount; i++) {
+ if(strcmp(Variables[i].name, name)==0) {
+ return Variables[i].val;
+ }
+ }
+ MarkUsedVariable(name, VAR_FLAG_OTHERWISE_FORGOTTEN);
+ return GetSimulationVariable(name);
+}
//-----------------------------------------------------------------------------
// Set the shadow copy of a variable associated with a READ ADC operation. This
// will get committed to the real copy when the rung-in condition to the
// READ ADC is true.
//-----------------------------------------------------------------------------
-// void SetAdcShadow(char *name, SWORD val)
-// {
-// int i;
-// for(i = 0; i < AdcShadowsCount; i++) {
-// if(strcmp(AdcShadows[i].name, name)==0) {
-// AdcShadows[i].val = val;
-// return;
-// }
-// }
-// strcpy(AdcShadows[i].name, name);
-// AdcShadows[i].val = val;
-// AdcShadowsCount++;
-// }
+void SetAdcShadow(char *name, SWORD val)
+{
+ int i;
+ for(i = 0; i < AdcShadowsCount; i++) {
+ if(strcmp(AdcShadows[i].name, name)==0) {
+ AdcShadows[i].val = val;
+ return;
+ }
+ }
+ strcpy(AdcShadows[i].name, name);
+ AdcShadows[i].val = val;
+ AdcShadowsCount++;
+}
//-----------------------------------------------------------------------------
// Return the shadow value of a variable associated with a READ ADC. This is
// what gets copied into the real variable when an ADC read is simulated.
//-----------------------------------------------------------------------------
-// SWORD GetAdcShadow(char *name)
-// {
-// int i;
-// for(i = 0; i < AdcShadowsCount; i++) {
-// if(strcmp(AdcShadows[i].name, name)==0) {
-// return AdcShadows[i].val;
-// }
-// }
-// return 0;
-// }
+SWORD GetAdcShadow(char *name)
+{
+ int i;
+ for(i = 0; i < AdcShadowsCount; i++) {
+ if(strcmp(AdcShadows[i].name, name)==0) {
+ return AdcShadows[i].val;
+ }
+ }
+ return 0;
+}
//-----------------------------------------------------------------------------
// Mark how a variable is used; a series of flags that we can OR together,
@@ -224,62 +224,62 @@ static char *MarkUsedVariable(char *name, DWORD flag);
// (e.g. just a TON, an RTO with its reset, etc.). Returns NULL for success,
// else an error string.
//-----------------------------------------------------------------------------
-// static char *MarkUsedVariable(char *name, DWORD flag)
-// {
-// int i;
-// for(i = 0; i < VariablesCount; i++) {
-// if(strcmp(Variables[i].name, name)==0) {
-// break;
-// }
-// }
-// if(i >= MAX_IO) return "";
-
-// if(i == VariablesCount) {
-// strcpy(Variables[i].name, name);
-// Variables[i].usedFlags = 0;
-// Variables[i].val = 0;
-// VariablesCount++;
-// }
-
-// switch(flag) {
-// case VAR_FLAG_TOF:
-// if(Variables[i].usedFlags != 0)
-// return _("TOF: variable cannot be used elsewhere");
-// break;
-
-// case VAR_FLAG_TON:
-// if(Variables[i].usedFlags != 0)
-// return _("TON: variable cannot be used elsewhere");
-// break;
+static char *MarkUsedVariable(char *name, DWORD flag)
+{
+ int i;
+ for(i = 0; i < VariablesCount; i++) {
+ if(strcmp(Variables[i].name, name)==0) {
+ break;
+ }
+ }
+ if(i >= MAX_IO) return "";
+
+ if(i == VariablesCount) {
+ strcpy(Variables[i].name, name);
+ Variables[i].usedFlags = 0;
+ Variables[i].val = 0;
+ VariablesCount++;
+ }
+
+ switch(flag) {
+ case VAR_FLAG_TOF:
+ if(Variables[i].usedFlags != 0)
+ return _("TOF: variable cannot be used elsewhere");
+ break;
+
+ case VAR_FLAG_TON:
+ if(Variables[i].usedFlags != 0)
+ return _("TON: variable cannot be used elsewhere");
+ break;
-// case VAR_FLAG_RTO:
-// if(Variables[i].usedFlags & ~VAR_FLAG_RES)
-// return _("RTO: variable can only be used for RES elsewhere");
-// break;
-
-// case VAR_FLAG_CTU:
-// case VAR_FLAG_CTD:
-// case VAR_FLAG_CTC:
-// case VAR_FLAG_RES:
-// case VAR_FLAG_ANY:
-// break;
-
-// case VAR_FLAG_OTHERWISE_FORGOTTEN:
-// if(name[0] != '$') {
-// Error(_("Variable '%s' not assigned to, e.g. with a "
-// "MOV statement, an ADD statement, etc.\r\n\r\n"
-// "This is probably a programming error; now it "
-// "will always be zero."), name);
-// }
-// break;
-
-// default:
-// oops();
-// }
-
-// Variables[i].usedFlags |= flag;
-// return NULL;
-// }
+ case VAR_FLAG_RTO:
+ if(Variables[i].usedFlags & ~VAR_FLAG_RES)
+ return _("RTO: variable can only be used for RES elsewhere");
+ break;
+
+ case VAR_FLAG_CTU:
+ case VAR_FLAG_CTD:
+ case VAR_FLAG_CTC:
+ case VAR_FLAG_RES:
+ case VAR_FLAG_ANY:
+ break;
+
+ case VAR_FLAG_OTHERWISE_FORGOTTEN:
+ if(name[0] != '$') {
+ Error(_("Variable '%s' not assigned to, e.g. with a "
+ "MOV statement, an ADD statement, etc.\r\n\r\n"
+ "This is probably a programming error; now it "
+ "will always be zero."), name);
+ }
+ break;
+
+ default:
+ oops();
+ }
+
+ Variables[i].usedFlags |= flag;
+ return NULL;
+}
//-----------------------------------------------------------------------------
// Check for duplicate uses of a single variable. For example, there should
@@ -287,207 +287,207 @@ static char *MarkUsedVariable(char *name, DWORD flag);
// to have an RTO with the same name as its reset; in fact, verify that
// there must be a reset for each RTO.
//-----------------------------------------------------------------------------
-// static void MarkWithCheck(char *name, int flag)
-// {
-// char *s = MarkUsedVariable(name, flag);
-// if(s) {
-// Error(_("Variable for '%s' incorrectly assigned: %s."), name, s);
-// }
-// }
-
-// static void CheckVariableNamesCircuit(int which, void *elem)
-// {
-// ElemLeaf *l = (ElemLeaf *)elem;
-// char *name = NULL;
-// DWORD flag;
-
-// switch(which) {
-// case ELEM_SERIES_SUBCKT: {
-// int i;
-// ElemSubcktSeries *s = (ElemSubcktSeries *)elem;
-// for(i = 0; i < s->count; i++) {
-// CheckVariableNamesCircuit(s->contents[i].which,
-// s->contents[i].d.any);
-// }
-// break;
-// }
-
-// case ELEM_PARALLEL_SUBCKT: {
-// int i;
-// ElemSubcktParallel *p = (ElemSubcktParallel *)elem;
-// for(i = 0; i < p->count; i++) {
-// CheckVariableNamesCircuit(p->contents[i].which,
-// p->contents[i].d.any);
-// }
-// break;
-// }
+static void MarkWithCheck(char *name, int flag)
+{
+ char *s = MarkUsedVariable(name, flag);
+ if(s) {
+ Error(_("Variable for '%s' incorrectly assigned: %s."), name, s);
+ }
+}
+
+static void CheckVariableNamesCircuit(int which, void *elem)
+{
+ ElemLeaf *l = (ElemLeaf *)elem;
+ char *name = NULL;
+ DWORD flag;
+
+ switch(which) {
+ case ELEM_SERIES_SUBCKT: {
+ int i;
+ ElemSubcktSeries *s = (ElemSubcktSeries *)elem;
+ for(i = 0; i < s->count; i++) {
+ CheckVariableNamesCircuit(s->contents[i].which,
+ s->contents[i].d.any);
+ }
+ break;
+ }
+
+ case ELEM_PARALLEL_SUBCKT: {
+ int i;
+ ElemSubcktParallel *p = (ElemSubcktParallel *)elem;
+ for(i = 0; i < p->count; i++) {
+ CheckVariableNamesCircuit(p->contents[i].which,
+ p->contents[i].d.any);
+ }
+ break;
+ }
-// case ELEM_RTO:
-// case ELEM_TOF:
-// case ELEM_TON:
-// if(which == ELEM_RTO)
-// flag = VAR_FLAG_RTO;
-// else if(which == ELEM_TOF)
-// flag = VAR_FLAG_TOF;
-// else if(which == ELEM_TON)
-// flag = VAR_FLAG_TON;
-// else oops();
-
-// MarkWithCheck(l->d.timer.name, flag);
-
-// break;
-
-// case ELEM_CTU:
-// case ELEM_CTD:
-// case ELEM_CTC:
-// if(which == ELEM_CTU)
-// flag = VAR_FLAG_CTU;
-// else if(which == ELEM_CTD)
-// flag = VAR_FLAG_CTD;
-// else if(which == ELEM_CTC)
-// flag = VAR_FLAG_CTC;
-// else oops();
-
-// MarkWithCheck(l->d.counter.name, flag);
-
-// break;
-
-// case ELEM_RES:
-// MarkWithCheck(l->d.reset.name, VAR_FLAG_RES);
-// break;
-
-// case ELEM_MOVE:
-// MarkWithCheck(l->d.move.dest, VAR_FLAG_ANY);
-// break;
-
-// case ELEM_LOOK_UP_TABLE:
-// MarkWithCheck(l->d.lookUpTable.dest, VAR_FLAG_ANY);
-// break;
-
-// case ELEM_PIECEWISE_LINEAR:
-// MarkWithCheck(l->d.piecewiseLinear.dest, VAR_FLAG_ANY);
-// break;
-
-// case ELEM_READ_ADC:
-// MarkWithCheck(l->d.readAdc.name, VAR_FLAG_ANY);
-// break;
-
-// case ELEM_ADD:
-// case ELEM_SUB:
-// case ELEM_MUL:
-// case ELEM_DIV:
-// MarkWithCheck(l->d.math.dest, VAR_FLAG_ANY);
-// break;
-
-// case ELEM_UART_RECV:
-// MarkWithCheck(l->d.uart.name, VAR_FLAG_ANY);
-// break;
-
-// case ELEM_SHIFT_REGISTER: {
-// int i;
-// for(i = 1; i < l->d.shiftRegister.stages; i++) {
-// char str[MAX_NAME_LEN+10];
-// sprintf(str, "%s%d", l->d.shiftRegister.name, i);
-// MarkWithCheck(str, VAR_FLAG_ANY);
-// }
-// break;
-// }
-
-// case ELEM_PERSIST:
-// case ELEM_FORMATTED_STRING:
-// case ELEM_SET_PWM:
-// case ELEM_MASTER_RELAY:
-// case ELEM_UART_SEND:
-// case ELEM_PLACEHOLDER:
-// case ELEM_COMMENT:
-// case ELEM_OPEN:
-// case ELEM_SHORT:
-// case ELEM_COIL:
-// case ELEM_CONTACTS:
-// case ELEM_ONE_SHOT_RISING:
-// case ELEM_ONE_SHOT_FALLING:
-// case ELEM_EQU:
-// case ELEM_NEQ:
-// case ELEM_GRT:
-// case ELEM_GEQ:
-// case ELEM_LES:
-// case ELEM_LEQ:
-// break;
-
-// default:
-// oops();
-// }
-// }
-
-// static void CheckVariableNames(void)
-// {
-// int i;
-// for(i = 0; i < Prog.numRungs; i++) {
-// CheckVariableNamesCircuit(ELEM_SERIES_SUBCKT, Prog.rungs[i]);
-// }
-// }
+ case ELEM_RTO:
+ case ELEM_TOF:
+ case ELEM_TON:
+ if(which == ELEM_RTO)
+ flag = VAR_FLAG_RTO;
+ else if(which == ELEM_TOF)
+ flag = VAR_FLAG_TOF;
+ else if(which == ELEM_TON)
+ flag = VAR_FLAG_TON;
+ else oops();
+
+ MarkWithCheck(l->d.timer.name, flag);
+
+ break;
+
+ case ELEM_CTU:
+ case ELEM_CTD:
+ case ELEM_CTC:
+ if(which == ELEM_CTU)
+ flag = VAR_FLAG_CTU;
+ else if(which == ELEM_CTD)
+ flag = VAR_FLAG_CTD;
+ else if(which == ELEM_CTC)
+ flag = VAR_FLAG_CTC;
+ else oops();
+
+ MarkWithCheck(l->d.counter.name, flag);
+
+ break;
+
+ case ELEM_RES:
+ MarkWithCheck(l->d.reset.name, VAR_FLAG_RES);
+ break;
+
+ case ELEM_MOVE:
+ MarkWithCheck(l->d.move.dest, VAR_FLAG_ANY);
+ break;
+
+ case ELEM_LOOK_UP_TABLE:
+ MarkWithCheck(l->d.lookUpTable.dest, VAR_FLAG_ANY);
+ break;
+
+ case ELEM_PIECEWISE_LINEAR:
+ MarkWithCheck(l->d.piecewiseLinear.dest, VAR_FLAG_ANY);
+ break;
+
+ case ELEM_READ_ADC:
+ MarkWithCheck(l->d.readAdc.name, VAR_FLAG_ANY);
+ break;
+
+ case ELEM_ADD:
+ case ELEM_SUB:
+ case ELEM_MUL:
+ case ELEM_DIV:
+ MarkWithCheck(l->d.math.dest, VAR_FLAG_ANY);
+ break;
+
+ case ELEM_UART_RECV:
+ MarkWithCheck(l->d.uart.name, VAR_FLAG_ANY);
+ break;
+
+ case ELEM_SHIFT_REGISTER: {
+ int i;
+ for(i = 1; i < l->d.shiftRegister.stages; i++) {
+ char str[MAX_NAME_LEN+10];
+ sprintf(str, "%s%d", l->d.shiftRegister.name, i);
+ MarkWithCheck(str, VAR_FLAG_ANY);
+ }
+ break;
+ }
+
+ case ELEM_PERSIST:
+ case ELEM_FORMATTED_STRING:
+ case ELEM_SET_PWM:
+ case ELEM_MASTER_RELAY:
+ case ELEM_UART_SEND:
+ case ELEM_PLACEHOLDER:
+ case ELEM_COMMENT:
+ case ELEM_OPEN:
+ case ELEM_SHORT:
+ case ELEM_COIL:
+ case ELEM_CONTACTS:
+ case ELEM_ONE_SHOT_RISING:
+ case ELEM_ONE_SHOT_FALLING:
+ case ELEM_EQU:
+ case ELEM_NEQ:
+ case ELEM_GRT:
+ case ELEM_GEQ:
+ case ELEM_LES:
+ case ELEM_LEQ:
+ break;
+
+ default:
+ oops();
+ }
+}
+
+static void CheckVariableNames(void)
+{
+ int i;
+ for(i = 0; i < Prog.numRungs; i++) {
+ CheckVariableNamesCircuit(ELEM_SERIES_SUBCKT, Prog.rungs[i]);
+ }
+}
//-----------------------------------------------------------------------------
// The IF condition is true. Execute the body, up until the ELSE or the
// END IF, and then skip the ELSE if it is present. Called with PC on the
// IF, returns with PC on the END IF.
//-----------------------------------------------------------------------------
-// static void IfConditionTrue(void)
-// {
-// IntPc++;
-// // now PC is on the first statement of the IF body
-// SimulateIntCode();
-// // now PC is on the ELSE or the END IF
-// if(IntCode[IntPc].op == INT_ELSE) {
-// int nesting = 1;
-// for(; ; IntPc++) {
-// if(IntPc >= IntCodeLen) oops();
-
-// if(IntCode[IntPc].op == INT_END_IF) {
-// nesting--;
-// } else if(INT_IF_GROUP(IntCode[IntPc].op)) {
-// nesting++;
-// }
-// if(nesting == 0) break;
-// }
-// } else if(IntCode[IntPc].op == INT_END_IF) {
-// return;
-// } else {
-// oops();
-// }
-// }
+static void IfConditionTrue(void)
+{
+ IntPc++;
+ // now PC is on the first statement of the IF body
+ SimulateIntCode();
+ // now PC is on the ELSE or the END IF
+ if(IntCode[IntPc].op == INT_ELSE) {
+ int nesting = 1;
+ for(; ; IntPc++) {
+ if(IntPc >= IntCodeLen) oops();
+
+ if(IntCode[IntPc].op == INT_END_IF) {
+ nesting--;
+ } else if(INT_IF_GROUP(IntCode[IntPc].op)) {
+ nesting++;
+ }
+ if(nesting == 0) break;
+ }
+ } else if(IntCode[IntPc].op == INT_END_IF) {
+ return;
+ } else {
+ oops();
+ }
+}
//-----------------------------------------------------------------------------
// The IF condition is false. Skip the body, up until the ELSE or the END
// IF, and then execute the ELSE if it is present. Called with PC on the IF,
// returns with PC on the END IF.
//-----------------------------------------------------------------------------
-// static void IfConditionFalse(void)
-// {
-// int nesting = 0;
-// for(; ; IntPc++) {
-// if(IntPc >= IntCodeLen) oops();
-
-// if(IntCode[IntPc].op == INT_END_IF) {
-// nesting--;
-// } else if(INT_IF_GROUP(IntCode[IntPc].op)) {
-// nesting++;
-// } else if(IntCode[IntPc].op == INT_ELSE && nesting == 1) {
-// break;
-// }
-// if(nesting == 0) break;
-// }
-
-// // now PC is on the ELSE or the END IF
-// if(IntCode[IntPc].op == INT_ELSE) {
-// IntPc++;
-// SimulateIntCode();
-// } else if(IntCode[IntPc].op == INT_END_IF) {
-// return;
-// } else {
-// oops();
-// }
-// }
+static void IfConditionFalse(void)
+{
+ int nesting = 0;
+ for(; ; IntPc++) {
+ if(IntPc >= IntCodeLen) oops();
+
+ if(IntCode[IntPc].op == INT_END_IF) {
+ nesting--;
+ } else if(INT_IF_GROUP(IntCode[IntPc].op)) {
+ nesting++;
+ } else if(IntCode[IntPc].op == INT_ELSE && nesting == 1) {
+ break;
+ }
+ if(nesting == 0) break;
+ }
+
+ // now PC is on the ELSE or the END IF
+ if(IntCode[IntPc].op == INT_ELSE) {
+ IntPc++;
+ SimulateIntCode();
+ } else if(IntCode[IntPc].op == INT_END_IF) {
+ return;
+ } else {
+ oops();
+ }
+}
//-----------------------------------------------------------------------------
// Evaluate a circuit, calling ourselves recursively to evaluate if/else
@@ -495,229 +495,231 @@ static char *MarkUsedVariable(char *name, DWORD flag);
// internal tables. Returns when it reaches an end if or an else construct,
// or at the end of the program.
//-----------------------------------------------------------------------------
-// static void SimulateIntCode(void)
-// {
-// for(; IntPc < IntCodeLen; IntPc++) {
-// IntOp *a = &IntCode[IntPc];
-// switch(a->op) {
-// case INT_SIMULATE_NODE_STATE:
-// if(*(a->poweredAfter) != SingleBitOn(a->name1))
-// NeedRedraw = TRUE;
-// *(a->poweredAfter) = SingleBitOn(a->name1);
-// break;
-
-// case INT_SET_BIT:
-// SetSingleBit(a->name1, TRUE);
-// break;
-
-// case INT_CLEAR_BIT:
-// SetSingleBit(a->name1, FALSE);
-// break;
-
-// case INT_COPY_BIT_TO_BIT:
-// SetSingleBit(a->name1, SingleBitOn(a->name2));
-// break;
-
-// case INT_SET_VARIABLE_TO_LITERAL:
-// if(GetSimulationVariable(a->name1) !=
-// a->literal && a->name1[0] != '$')
-// {
-// NeedRedraw = TRUE;
-// }
-// SetSimulationVariable(a->name1, a->literal);
-// break;
-
-// case INT_SET_VARIABLE_TO_VARIABLE:
-// if(GetSimulationVariable(a->name1) !=
-// GetSimulationVariable(a->name2))
-// {
-// NeedRedraw = TRUE;
-// }
-// SetSimulationVariable(a->name1,
-// GetSimulationVariable(a->name2));
-// break;
-
-// case INT_INCREMENT_VARIABLE:
-// IncrementVariable(a->name1);
-// break;
-
-// {
-// SWORD v;
-// case INT_SET_VARIABLE_ADD:
-// v = GetSimulationVariable(a->name2) +
-// GetSimulationVariable(a->name3);
-// goto math;
-// case INT_SET_VARIABLE_SUBTRACT:
-// v = GetSimulationVariable(a->name2) -
-// GetSimulationVariable(a->name3);
-// goto math;
-// case INT_SET_VARIABLE_MULTIPLY:
-// v = GetSimulationVariable(a->name2) *
-// GetSimulationVariable(a->name3);
-// goto math;
-// case INT_SET_VARIABLE_DIVIDE:
-// if(GetSimulationVariable(a->name3) != 0) {
-// v = GetSimulationVariable(a->name2) /
-// GetSimulationVariable(a->name3);
-// } else {
-// v = 0;
-// Error(_("Division by zero; halting simulation"));
-// StopSimulation();
-// }
-// goto math;
-// math:
-// if(GetSimulationVariable(a->name1) != v) {
-// NeedRedraw = TRUE;
-// SetSimulationVariable(a->name1, v);
-// }
-// break;
-// }
-
-// #define IF_BODY \
-// { \
-// IfConditionTrue(); \
-// } else { \
-// IfConditionFalse(); \
-// }
-// case INT_IF_BIT_SET:
-// if(SingleBitOn(a->name1))
-// IF_BODY
-// break;
-
-// case INT_IF_BIT_CLEAR:
-// if(!SingleBitOn(a->name1))
-// IF_BODY
-// break;
-
-// case INT_IF_VARIABLE_LES_LITERAL:
-// if(GetSimulationVariable(a->name1) < a->literal)
-// IF_BODY
-// break;
-
-// case INT_IF_VARIABLE_EQUALS_VARIABLE:
-// if(GetSimulationVariable(a->name1) ==
-// GetSimulationVariable(a->name2))
-// IF_BODY
-// break;
-
-// case INT_IF_VARIABLE_GRT_VARIABLE:
-// if(GetSimulationVariable(a->name1) >
-// GetSimulationVariable(a->name2))
-// IF_BODY
-// break;
-
-// case INT_SET_PWM:
-// // Dummy call will cause a warning if no one ever assigned
-// // to that variable.
-// (void)GetSimulationVariable(a->name1);
-// break;
-
-// // Don't try to simulate the EEPROM stuff: just hold the EEPROM
-// // busy all the time, so that the program never does anything
-// // with it.
-// case INT_EEPROM_BUSY_CHECK:
-// SetSingleBit(a->name1, TRUE);
-// break;
-
-// case INT_EEPROM_READ:
-// case INT_EEPROM_WRITE:
-// oops();
-// break;
-
-// case INT_READ_ADC:
-// // Keep the shadow copies of the ADC variables because in
-// // the real device they will not be updated until an actual
-// // read is performed, which occurs only for a true rung-in
-// // condition there.
-// SetSimulationVariable(a->name1, GetAdcShadow(a->name1));
-// break;
-
-// case INT_UART_SEND:
-// if(SingleBitOn(a->name2) && (SimulateUartTxCountdown == 0)) {
-// SimulateUartTxCountdown = 2;
-// AppendToUartSimulationTextControl(
-// (BYTE)GetSimulationVariable(a->name1));
-// }
-// if(SimulateUartTxCountdown == 0) {
-// SetSingleBit(a->name2, FALSE);
-// } else {
-// SetSingleBit(a->name2, TRUE);
-// }
-// break;
-
-// case INT_UART_RECV:
-// if(QueuedUartCharacter >= 0) {
-// SetSingleBit(a->name2, TRUE);
-// SetSimulationVariable(a->name1, (SWORD)QueuedUartCharacter);
-// QueuedUartCharacter = -1;
-// } else {
-// SetSingleBit(a->name2, FALSE);
-// }
-// break;
-
-// case INT_END_IF:
-// case INT_ELSE:
-// return;
-
-// case INT_COMMENT:
-// break;
+static void SimulateIntCode(void)
+{
+ for(; IntPc < IntCodeLen; IntPc++) {
+ IntOp *a = &IntCode[IntPc];
+ switch(a->op) {
+ case INT_SIMULATE_NODE_STATE:
+ if(*(a->poweredAfter) != SingleBitOn(a->name1))
+ NeedRedraw = TRUE;
+ *(a->poweredAfter) = SingleBitOn(a->name1);
+ break;
+
+ case INT_SET_BIT:
+ SetSingleBit(a->name1, TRUE);
+ break;
+
+ case INT_CLEAR_BIT:
+ SetSingleBit(a->name1, FALSE);
+ break;
+
+ case INT_COPY_BIT_TO_BIT:
+ SetSingleBit(a->name1, SingleBitOn(a->name2));
+ break;
+
+ case INT_SET_VARIABLE_TO_LITERAL:
+ if(GetSimulationVariable(a->name1) !=
+ a->literal && a->name1[0] != '$')
+ {
+ NeedRedraw = TRUE;
+ }
+ SetSimulationVariable(a->name1, a->literal);
+ break;
+
+ case INT_SET_VARIABLE_TO_VARIABLE:
+ if(GetSimulationVariable(a->name1) !=
+ GetSimulationVariable(a->name2))
+ {
+ NeedRedraw = TRUE;
+ }
+ SetSimulationVariable(a->name1,
+ GetSimulationVariable(a->name2));
+ break;
+
+ case INT_INCREMENT_VARIABLE:
+ IncrementVariable(a->name1);
+ break;
+
+ {
+ SWORD v;
+ case INT_SET_VARIABLE_ADD:
+ v = GetSimulationVariable(a->name2) +
+ GetSimulationVariable(a->name3);
+ goto math;
+ case INT_SET_VARIABLE_SUBTRACT:
+ v = GetSimulationVariable(a->name2) -
+ GetSimulationVariable(a->name3);
+ goto math;
+ case INT_SET_VARIABLE_MULTIPLY:
+ v = GetSimulationVariable(a->name2) *
+ GetSimulationVariable(a->name3);
+ goto math;
+ case INT_SET_VARIABLE_DIVIDE:
+ if(GetSimulationVariable(a->name3) != 0) {
+ v = GetSimulationVariable(a->name2) /
+ GetSimulationVariable(a->name3);
+ } else {
+ v = 0;
+ Error(_("Division by zero; halting simulation"));
+ StopSimulation();
+ }
+ goto math;
+math:
+ if(GetSimulationVariable(a->name1) != v) {
+ NeedRedraw = TRUE;
+ SetSimulationVariable(a->name1, v);
+ }
+ break;
+ }
+
+#define IF_BODY \
+ { \
+ IfConditionTrue(); \
+ } else { \
+ IfConditionFalse(); \
+ }
+ case INT_IF_BIT_SET:
+ if(SingleBitOn(a->name1))
+ IF_BODY
+ break;
+
+ case INT_IF_BIT_CLEAR:
+ if(!SingleBitOn(a->name1))
+ IF_BODY
+ break;
+
+ case INT_IF_VARIABLE_LES_LITERAL:
+ if(GetSimulationVariable(a->name1) < a->literal)
+ IF_BODY
+ break;
+
+ case INT_IF_VARIABLE_EQUALS_VARIABLE:
+ if(GetSimulationVariable(a->name1) ==
+ GetSimulationVariable(a->name2))
+ IF_BODY
+ break;
+
+ case INT_IF_VARIABLE_GRT_VARIABLE:
+ if(GetSimulationVariable(a->name1) >
+ GetSimulationVariable(a->name2))
+ IF_BODY
+ break;
+
+ case INT_SET_PWM:
+ // Dummy call will cause a warning if no one ever assigned
+ // to that variable.
+ (void)GetSimulationVariable(a->name1);
+ break;
+
+ // Don't try to simulate the EEPROM stuff: just hold the EEPROM
+ // busy all the time, so that the program never does anything
+ // with it.
+ case INT_EEPROM_BUSY_CHECK:
+ SetSingleBit(a->name1, TRUE);
+ break;
+
+ case INT_EEPROM_READ:
+ case INT_EEPROM_WRITE:
+ oops();
+ break;
+
+ case INT_READ_ADC:
+ // Keep the shadow copies of the ADC variables because in
+ // the real device they will not be updated until an actual
+ // read is performed, which occurs only for a true rung-in
+ // condition there.
+ SetSimulationVariable(a->name1, GetAdcShadow(a->name1));
+ break;
+
+ case INT_UART_SEND:
+ if(SingleBitOn(a->name2) && (SimulateUartTxCountdown == 0)) {
+ SimulateUartTxCountdown = 2;
+ AppendToUartSimulationTextControl(
+ (BYTE)GetSimulationVariable(a->name1));
+ }
+ if(SimulateUartTxCountdown == 0) {
+ SetSingleBit(a->name2, FALSE);
+ } else {
+ SetSingleBit(a->name2, TRUE);
+ }
+ break;
+
+ case INT_UART_RECV:
+ if(QueuedUartCharacter >= 0) {
+ SetSingleBit(a->name2, TRUE);
+ SetSimulationVariable(a->name1, (SWORD)QueuedUartCharacter);
+ QueuedUartCharacter = -1;
+ } else {
+ SetSingleBit(a->name2, FALSE);
+ }
+ break;
+
+ case INT_END_IF:
+ case INT_ELSE:
+ return;
+
+ case INT_COMMENT:
+ break;
-// default:
-// oops();
-// break;
-// }
-// }
-// }
+ default:
+ oops();
+ break;
+ }
+ }
+}
//-----------------------------------------------------------------------------
// Called by the Windows timer that triggers cycles when we are running
// in real time.
//-----------------------------------------------------------------------------
-// void CALLBACK PlcCycleTimer(HWND hwnd, UINT msg, UINT_PTR id, DWORD time)
-// {
-// int i;
-// for(i = 0; i < CyclesPerTimerTick; i++) {
-// SimulateOneCycle(FALSE);
-// }
-// }
+BOOL PlcCycleTimer(BOOL kill = FALSE)
+{
+ for(int i = 0; i < CyclesPerTimerTick; i++) {
+ SimulateOneCycle(FALSE);
+ }
+
+ return !kill;
+}
//-----------------------------------------------------------------------------
// Simulate one cycle of the PLC. Update everything, and keep track of whether
// any outputs have changed. If so, force a screen refresh. If requested do
// a screen refresh regardless.
//-----------------------------------------------------------------------------
-// void SimulateOneCycle(BOOL forceRefresh)
-// {
-// // When there is an error message up, the modal dialog makes its own
-// // event loop, and there is risk that we would go recursive. So let
-// // us fix that. (Note that there are no concurrency issues; we really
-// // would get called recursively, not just reentrantly.)
-// static BOOL Simulating = FALSE;
+void SimulateOneCycle(BOOL forceRefresh)
+{
+ // When there is an error message up, the modal dialog makes its own
+ // event loop, and there is risk that we would go recursive. So let
+ // us fix that. (Note that there are no concurrency issues; we really
+ // would get called recursively, not just reentrantly.)
+ static BOOL Simulating = FALSE;
-// if(Simulating) return;
-// Simulating = TRUE;
+ if(Simulating) return;
+ Simulating = TRUE;
-// NeedRedraw = FALSE;
+ NeedRedraw = FALSE;
-// if(SimulateUartTxCountdown > 0) {
-// SimulateUartTxCountdown--;
-// } else {
-// SimulateUartTxCountdown = 0;
-// }
+ if(SimulateUartTxCountdown > 0) {
+ SimulateUartTxCountdown--;
+ } else {
+ SimulateUartTxCountdown = 0;
+ }
-// IntPc = 0;
-// SimulateIntCode();
+ IntPc = 0;
+ SimulateIntCode();
-// if(NeedRedraw || SimulateRedrawAfterNextCycle || forceRefresh) {
-// InvalidateRect(MainWindow, NULL, FALSE);
-// ListView_RedrawItems(IoList, 0, Prog.io.count - 1);
-// }
+ if(NeedRedraw || SimulateRedrawAfterNextCycle || forceRefresh) {
+ InvalidateRect(DrawWindow, NULL, FALSE);
+ gtk_widget_queue_draw(DrawWindow);
+ // ListView_RedrawItems(IoList, 0, Prog.io.count - 1);
+ }
-// SimulateRedrawAfterNextCycle = FALSE;
-// if(NeedRedraw) SimulateRedrawAfterNextCycle = TRUE;
+ SimulateRedrawAfterNextCycle = FALSE;
+ if(NeedRedraw) SimulateRedrawAfterNextCycle = TRUE;
-// Simulating = FALSE;
-// }
+ Simulating = FALSE;
+}
//-----------------------------------------------------------------------------
// Start the timer that we use to trigger PLC cycles in approximately real
@@ -725,81 +727,81 @@ static char *MarkUsedVariable(char *name, DWORD flag);
// is about as fast as anyone could follow by eye. Faster timers will just
// go instantly.
//-----------------------------------------------------------------------------
-// void StartSimulationTimer(void)
-// {
-// int p = Prog.cycleTime/1000;
-// if(p < 5) {
-// SetTimer(MainWindow, TIMER_SIMULATE, 10, PlcCycleTimer);
-// CyclesPerTimerTick = 10000 / Prog.cycleTime;
-// } else {
-// SetTimer(MainWindow, TIMER_SIMULATE, p, PlcCycleTimer);
-// CyclesPerTimerTick = 1;
-// }
-// }
+void StartSimulationTimer(void)
+{
+ int p = Prog.cycleTime/1000;
+ if(p < 5) {
+ SetTimer(MainWindow, TIMER_SIMULATE, 10, PlcCycleTimer);
+ CyclesPerTimerTick = 10000 / Prog.cycleTime;
+ } else {
+ SetTimer(MainWindow, TIMER_SIMULATE, p, PlcCycleTimer);
+ CyclesPerTimerTick = 1;
+ }
+}
//-----------------------------------------------------------------------------
// Clear out all the parameters relating to the previous simulation.
//-----------------------------------------------------------------------------
-// void ClearSimulationData(void)
-// {
-// VariablesCount = 0;
-// SingleBitItemsCount = 0;
-// AdcShadowsCount = 0;
-// QueuedUartCharacter = -1;
-// SimulateUartTxCountdown = 0;
+void ClearSimulationData(void)
+{
+ VariablesCount = 0;
+ SingleBitItemsCount = 0;
+ AdcShadowsCount = 0;
+ QueuedUartCharacter = -1;
+ SimulateUartTxCountdown = 0;
-// CheckVariableNames();
+ CheckVariableNames();
-// SimulateRedrawAfterNextCycle = TRUE;
+ SimulateRedrawAfterNextCycle = TRUE;
-// if(!GenerateIntermediateCode()) {
-// ToggleSimulationMode();
-// return;
-// }
+ if(!GenerateIntermediateCode()) {
+ ToggleSimulationMode();
+ return;
+ }
-// SimulateOneCycle(TRUE);
-// }
+ SimulateOneCycle(TRUE);
+}
//-----------------------------------------------------------------------------
// Provide a description for an item (Xcontacts, Ycoil, Rrelay, Ttimer,
// or other) in the I/O list.
//-----------------------------------------------------------------------------
-// void DescribeForIoList(char *name, char *out)
-// {
-// switch(name[0]) {
-// case 'R':
-// case 'X':
-// case 'Y':
-// sprintf(out, "%d", SingleBitOn(name));
-// break;
-
-// case 'T': {
-// double dtms = GetSimulationVariable(name) *
-// (Prog.cycleTime / 1000.0);
-// if(dtms < 1000) {
-// sprintf(out, "%.2f ms", dtms);
-// } else {
-// sprintf(out, "%.3f s", dtms / 1000);
-// }
-// break;
-// }
-// default: {
-// SWORD v = GetSimulationVariable(name);
-// sprintf(out, "%hd (0x%04hx)", v, v);
-// break;
-// }
-// }
-// }
+void DescribeForIoList(char *name, char *out)
+{
+ switch(name[0]) {
+ case 'R':
+ case 'X':
+ case 'Y':
+ sprintf(out, "%d", SingleBitOn(name));
+ break;
+
+ case 'T': {
+ double dtms = GetSimulationVariable(name) *
+ (Prog.cycleTime / 1000.0);
+ if(dtms < 1000) {
+ sprintf(out, "%.2f ms", dtms);
+ } else {
+ sprintf(out, "%.3f s", dtms / 1000);
+ }
+ break;
+ }
+ default: {
+ SWORD v = GetSimulationVariable(name);
+ sprintf(out, "%hd (0x%04hx)", v, v);
+ break;
+ }
+ }
+}
//-----------------------------------------------------------------------------
// Toggle the state of a contact input; for simulation purposes, so that we
// can set the input state of the program.
//-----------------------------------------------------------------------------
-// void SimulationToggleContact(char *name)
-// {
-// SetSingleBit(name, !SingleBitOn(name));
-// ListView_RedrawItems(IoList, 0, Prog.io.count - 1);
-// }
+void SimulationToggleContact(char *name)
+{
+ SetSingleBit(name, !SingleBitOn(name));
+ // ListView_RedrawItems(IoList, 0, Prog.io.count - 1);
+}
//-----------------------------------------------------------------------------
// Dialog proc for the popup that lets you interact with the UART stuff.
@@ -835,140 +837,154 @@ static char *MarkUsedVariable(char *name, DWORD flag);
//-----------------------------------------------------------------------------
// Intercept WM_CHAR messages that to the terminal simulation window so that
// we can redirect them to the PLC program.
-//-----------------------------------------------------------------------------
-// static LRESULT CALLBACK UartSimulationTextProc(HWND hwnd, UINT msg,
-// WPARAM wParam, LPARAM lParam)
-// {
-// if(msg == WM_CHAR) {
-// QueuedUartCharacter = (BYTE)wParam;
-// return 0;
-// }
-
-// return CallWindowProc((WNDPROC)PrevTextProc, hwnd, msg, wParam, lParam);
-// }
+//
+// Ported: Read and write text fron the text view widget.
+//-----------------------------------------------------------------------------
+static void UartSimulationTextProc(HWID hwid, UINT umsg, char *text, UINT uszbuf)
+{
+ switch(umsg)
+ {
+ case WM_SETTEXT:
+ {
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(hwid));
+ gtk_text_buffer_set_text (buffer, text, -1);
+ gtk_text_view_set_buffer (GTK_TEXT_VIEW(hwid), buffer);
+
+ GtkTextIter end;
+ gtk_text_buffer_get_end_iter (buffer, &end);
+ gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(hwid), &end, 0.2, FALSE, 1, 1);
+ break;
+ }
+ case WM_SETTEXT_END:
+ {
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(hwid));
+ gtk_text_buffer_insert_at_cursor (buffer, text, -1);
+ gtk_text_view_set_buffer (GTK_TEXT_VIEW(hwid), buffer);
+
+ GtkTextIter end;
+ gtk_text_buffer_get_end_iter (buffer, &end);
+ gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(hwid), &end, 0.2, FALSE, 1, 1);
+ break;
+ }
+ case WM_GETTEXT:
+ {
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(hwid));
+ GtkTextIter start, end;
+ gtk_text_buffer_get_start_iter (buffer, &start);
+ gtk_text_buffer_get_end_iter (buffer, &end);
+
+ char *txtBuf = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+
+ strcpy(text, txtBuf);
+ strcat(text, "\0");
+ g_free(txtBuf);
+ break;
+ }
+ default:
+ break;
+ }
+}
//-----------------------------------------------------------------------------
// Pop up the UART simulation window; like a terminal window where the
// characters that you type go into UART RECV instruction and whatever
// the program puts into UART SEND shows up as text.
//-----------------------------------------------------------------------------
-// void ShowUartSimulationWindow(void)
-// {
-// WNDCLASSEX wc;
-// memset(&wc, 0, sizeof(wc));
-// wc.cbSize = sizeof(wc);
-
-// wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC |
-// CS_DBLCLKS;
-// wc.lpfnWndProc = (WNDPROC)UartSimulationProc;
-// wc.hInstance = Instance;
-// wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
-// wc.lpszClassName = "LDmicroUartSimulationWindow";
-// wc.lpszMenuName = NULL;
-// wc.hCursor = LoadCursor(NULL, IDC_ARROW);
-
-// RegisterClassEx(&wc);
-
-// DWORD TerminalX = 200, TerminalY = 200, TerminalW = 300, TerminalH = 150;
-
-// ThawDWORD(TerminalX);
-// ThawDWORD(TerminalY);
-// ThawDWORD(TerminalW);
-// ThawDWORD(TerminalH);
-
-// if(TerminalW > 800) TerminalW = 100;
-// if(TerminalH > 800) TerminalH = 100;
-
-// RECT r;
-// GetClientRect(GetDesktopWindow(), &r);
-// if(TerminalX >= (DWORD)(r.right - 10)) TerminalX = 100;
-// if(TerminalY >= (DWORD)(r.bottom - 10)) TerminalY = 100;
-
-// UartSimulationWindow = CreateWindowClient(WS_EX_TOOLWINDOW |
-// WS_EX_APPWINDOW, "LDmicroUartSimulationWindow",
-// "UART Simulation (Terminal)", WS_VISIBLE | WS_SIZEBOX,
-// TerminalX, TerminalY, TerminalW, TerminalH,
-// NULL, NULL, Instance, NULL);
-
-// UartSimulationTextControl = CreateWindowEx(0, WC_EDIT, "", WS_CHILD |
-// WS_CLIPSIBLINGS | WS_VISIBLE | ES_AUTOVSCROLL | ES_MULTILINE |
-// WS_VSCROLL, 0, 0, TerminalW, TerminalH, UartSimulationWindow, NULL,
-// Instance, NULL);
-
-// HFONT fixedFont = CreateFont(14, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
-// ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
-// FF_DONTCARE, "Lucida Console");
-// if(!fixedFont)
-// fixedFont = (HFONT)GetStockObject(SYSTEM_FONT);
-
-// SendMessage((HWND)UartSimulationTextControl, WM_SETFONT, (WPARAM)fixedFont,
-// TRUE);
-
-// PrevTextProc = SetWindowLongPtr(UartSimulationTextControl,
-// GWLP_WNDPROC, (LONG_PTR)UartSimulationTextProc);
-
-// ShowWindow(UartSimulationWindow, TRUE);
-// SetFocus(MainWindow);
-// }
+void ShowUartSimulationWindow(void)
+{
+ DWORD TerminalX = 200, TerminalY = 200, TerminalW = 300, TerminalH = 150;
+
+ ThawDWORD(TerminalX);
+ ThawDWORD(TerminalY);
+ ThawDWORD(TerminalW);
+ ThawDWORD(TerminalH);
+
+ if(TerminalW > 800) TerminalW = 100;
+ if(TerminalH > 800) TerminalH = 100;
+
+ UartSimulationWindow = CreateWindowClient(GTK_WINDOW_TOPLEVEL, GDK_WINDOW_TYPE_HINT_NORMAL,
+ "UART Simulation (Terminal)", TerminalX, TerminalY, TerminalW, TerminalH, NULL);
+ /// remove close button
+ gtk_window_set_deletable (GTK_WINDOW(UartSimulationWindow), FALSE);
+
+ UartSimulationTextControl = gtk_text_view_new();
+
+ gtk_widget_override_font(GTK_WIDGET(UartSimulationTextControl), pango_font_description_from_string("Lucida Console"));
+
+ /// Add text view into a scrolled window to enable scrolling functionality
+ HWID TextViewScroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (TextViewScroll),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_widget_set_hexpand(GTK_WIDGET(TextViewScroll), TRUE);
+ gtk_widget_set_vexpand(GTK_WIDGET(TextViewScroll), TRUE);
+
+ gtk_container_add (GTK_CONTAINER(TextViewScroll), UartSimulationTextControl);
+ gtk_container_add (GTK_CONTAINER(UartSimulationWindow), TextViewScroll);
+
+ gtk_widget_show_all(UartSimulationWindow);
+
+ gtk_window_set_keep_above (GTK_WINDOW(MainWindow), TRUE);
+ gtk_window_set_focus_visible (GTK_WINDOW(MainWindow), TRUE);
+ gtk_window_set_keep_above (GTK_WINDOW(MainWindow), FALSE);
+}
//-----------------------------------------------------------------------------
// Get rid of the UART simulation terminal-type window.
//-----------------------------------------------------------------------------
-// void DestroyUartSimulationWindow(void)
-// {
-// // Try not to destroy the window if it is already destroyed; that is
-// // not for the sake of the window, but so that we don't trash the
-// // stored position.
-// if(UartSimulationWindow == NULL) return;
+void DestroyUartSimulationWindow(void)
+{
+ // Try not to destroy the window if it is already destroyed; that is
+ // not for the sake of the window, but so that we don't trash the
+ // stored position.
+ if(UartSimulationWindow == NULL) return;
-// DWORD TerminalX, TerminalY, TerminalW, TerminalH;
-// RECT r;
+ DWORD TerminalX, TerminalY, TerminalW, TerminalH;
+ RECT r;
-// GetClientRect(UartSimulationWindow, &r);
-// TerminalW = r.right - r.left;
-// TerminalH = r.bottom - r.top;
+ GetClientRect(UartSimulationWindow, &r);
+ TerminalW = r.right - r.left;
+ TerminalH = r.bottom - r.top;
-// GetWindowRect(UartSimulationWindow, &r);
-// TerminalX = r.left;
-// TerminalY = r.top;
+ GetWindowRect(UartSimulationWindow, &r);
+ TerminalX = r.left;
+ TerminalY = r.top;
-// FreezeDWORD(TerminalX);
-// FreezeDWORD(TerminalY);
-// FreezeDWORD(TerminalW);
-// FreezeDWORD(TerminalH);
+ FreezeDWORD(TerminalX);
+ FreezeDWORD(TerminalY);
+ FreezeDWORD(TerminalW);
+ FreezeDWORD(TerminalH);
-// DestroyWindow(UartSimulationWindow);
-// UartSimulationWindow = NULL;
-// }
+ DestroyWindow(UartSimulationWindow);
+ UartSimulationWindow = NULL;
+}
//-----------------------------------------------------------------------------
// Append a received character to the terminal buffer.
//-----------------------------------------------------------------------------
-// static void AppendToUartSimulationTextControl(BYTE b)
-// {
-// char append[5];
-
-// if((isalnum(b) || strchr("[]{};':\",.<>/?`~ !@#$%^&*()-=_+|", b) ||
-// b == '\r' || b == '\n') && b != '\0')
-// {
-// append[0] = b;
-// append[1] = '\0';
-// } else {
-// sprintf(append, "\\x%02x", b);
-// }
+static void AppendToUartSimulationTextControl(BYTE b)
+{
+ char append[5];
-// #define MAX_SCROLLBACK 256
-// char buf[MAX_SCROLLBACK];
+ if((isalnum(b) || strchr("[]{};':\",.<>/?`~ !@#$%^&*()-=_+|", b) ||
+ b == '\r' || b == '\n') && b != '\0')
+ {
+ append[0] = b;
+ append[1] = '\0';
+ } else {
+ sprintf(append, "\\x%02x", b);
+ }
-// SendMessage(UartSimulationTextControl, WM_GETTEXT, (WPARAM)sizeof(buf),
-// (LPARAM)buf);
+#define MAX_SCROLLBACK 256
+ char buf[MAX_SCROLLBACK];
-// int overBy = (strlen(buf) + strlen(append) + 1) - sizeof(buf);
-// if(overBy > 0) {
-// memmove(buf, buf + overBy, strlen(buf));
-// }
-// strcat(buf, append);
+ UartSimulationTextProc(UartSimulationTextControl, WM_GETTEXT, buf, strlen(buf));
-// SendMessage(UartSimulationTextControl, WM_SETTEXT, 0, (LPARAM)buf);
-// SendMessage(UartSimulationTextControl, EM_LINESCROLL, 0, (LPARAM)INT_MAX);
-// }
+ int overBy = (strlen(buf) + strlen(append) + 1) - sizeof(buf);
+ if(overBy > 0) {
+ memmove(buf, buf + overBy, strlen(buf));
+ }
+ strcat(buf, append);
+
+ UartSimulationTextProc(UartSimulationTextControl, WM_SETTEXT, buf, strlen(buf));
+}