1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11 
12 
13 #include "DXStrings.h"
14 #include "DXExecCtl.h"
15 #include "Command.h"
16 #include "DXApplication.h"
17 #include "DXPacketIF.h"
18 #include "List.h"
19 #include "ListIterator.h"
20 #include "Network.h"
21 #include "SequencerNode.h"
22 #include "ErrorDialogManager.h"
23 #include "ProcessGroupManager.h"
24 #include "../widgets/VCRControl.h"
25 
26 
DXExecCtl()27 DXExecCtl::DXExecCtl()
28 {
29     this->forceNetworkResend = TRUE;
30     this->forceParameterResend = TRUE;
31     this->execOnChange = FALSE;
32     this->execOnChangeSuspensions = 0;
33     this->isCurrentlyExecuting       = FALSE;
34     this->vcrIsExecuting    = FALSE;
35     this->resumeExecOnChangeAfterExecution = FALSE;
36     this->endExecOnChangePending = FALSE;
37 }
38 
39 void
forceFullResend()40 DXExecCtl::forceFullResend()
41 {
42     this->forceNetworkResend = TRUE;
43     this->forceParameterResend = TRUE;
44 
45 #if WORKSPACE_PAGES
46     GroupManager *pmgr = (GroupManager*)
47 	theDXApplication->network->getGroupManagers()->findDefinition (PROCESS_GROUP);
48     if (pmgr) pmgr->setDirty();
49 #else
50     if(theDXApplication->PGManager)
51 	theDXApplication->PGManager->setDirty();
52 #endif
53 
54     SequencerNode* sequencer = theDXApplication->network->sequencer;
55     if(sequencer)
56 	sequencer->transmitted = FALSE;
57 }
58 
59 void
BGBeginMessage(void * clientData,int id,void * p)60 DXExecCtl::BGBeginMessage(void *clientData, int id, void *p)
61 {
62     DXExecCtl *ctl = (DXExecCtl *)clientData;
63     ctl->beginSingleExecution(FALSE);
64 }
65 void
BGEndMessage(void * clientData,int id,void * p)66 DXExecCtl::BGEndMessage(void *clientData, int id, void *p)
67 {
68     DXExecCtl *ctl = (DXExecCtl *)clientData;
69     ctl->endLastExecution(!ctl->vcrIsExecuting);
70 }
71 
72 void
HWBeginMessage(void * clientData,int id,void * p)73 DXExecCtl::HWBeginMessage(void *clientData, int id, void *p)
74 {
75     DXExecCtl *ctl = (DXExecCtl *)clientData;
76 
77     if (!ctl->hwExecuting++ AND !ctl->isExecuting())
78         theDXApplication->notifyClients(DXApplication::MsgExecute);
79 }
80 void
HWEndMessage(void * clientData,int id,void * p)81 DXExecCtl::HWEndMessage(void *clientData, int id, void *p)
82 {
83     DXExecCtl *ctl = (DXExecCtl *)clientData;
84     Symbol msg = 0;
85     ASSERT(ctl->hwExecuting > 0);
86 
87     if (--ctl->hwExecuting <= 0 AND !ctl->isExecuting())
88 	msg = ctl->inExecOnChange() ? DXApplication::MsgStandBy :
89 				      DXApplication::MsgExecuteDone;
90 #ifdef SET_HW_BUSY_CURSOR
91     if (ctl->hwExecuting <= 0 AND ctl->hwBusy)
92     {
93 	theDXApplication->setBusyCursor(FALSE);
94 	ctl->hwBusy = FALSE;
95     }
96 #endif
97 
98     if (msg)
99         theDXApplication->notifyClients(msg);
100 }
101 
102 void
ExecComplete(void * clientData,int id,void * p)103 DXExecCtl::ExecComplete(void *clientData, int id, void *p)
104 {
105 
106     DXExecCtl *ctl = theDXApplication->getExecCtl();
107     SequencerNode* sequencer = theDXApplication->network->sequencer;
108 
109     //
110     // During VCR executing we turn off green lights and pop up
111     // the Play button ONLY when we receive "stop" command.
112     //
113     if (ctl->vcrIsExecuting AND !EqualString((char*)p, "stop"))
114 	return;
115 
116     ctl->endLastExecution(TRUE);
117 
118     if (ctl->vcrIsExecuting)
119     {
120     	if (sequencer)
121 	    sequencer->setPlayDirection(SequencerNode::Directionless);
122 	ctl->vcrIsExecuting = FALSE;
123     }
124 
125     if (!ctl->inExecOnChange() AND ctl->hwExecuting <= 0)
126         theDXApplication->notifyClients(DXApplication::MsgExecuteDone);
127     // else
128     //	MsgStandBy already sent by endLastExecution()
129 }
130 
131 void
ResumeExecOnChange(void * clientData,int id,void * p)132 DXExecCtl::ResumeExecOnChange(void *clientData, int id, void *p)
133 {
134 
135     DXExecCtl *ctl = theDXApplication->getExecCtl();
136     if(ctl->isExecOnChangeSuspended())
137     	ctl->resumeExecOnChange();
138 }
139 
newConnection()140 void DXExecCtl::newConnection()
141 {
142     DXPacketIF *p = theDXApplication->getPacketIF();
143 
144     ASSERT(p);
145 
146     p->setHandler(DXPacketIF::INTERRUPT,
147                   DXExecCtl::ExecComplete,
148                   (void*)theDXApplication->getExecCtl(),
149                   "stop");
150 
151     //
152     // highlighting handlers for HW rendering
153     //
154     this->hwExecuting = 0;
155     this->hwBusy      = FALSE;
156     p->setHandler(DXPacketIF::INFORMATION,
157 		  DXExecCtl::HWBeginMessage,
158 		  (void *)this,
159 		  "HW:  begin");
160     p->setHandler(DXPacketIF::INFORMATION,
161 		  DXExecCtl::HWEndMessage,
162 		  (void *)this,
163 		  "HW:  end");
164 
165     p->setHandler(DXPacketIF::INFORMATION,
166 		  DXExecCtl::BGBeginMessage,
167 		  (void *)this,
168 		  "BG:  begin");
169     p->setHandler(DXPacketIF::INFORMATION,
170 		  DXExecCtl::BGEndMessage,
171 		  (void *)this,
172 		  "BG:  end");
173 
174     SequencerNode* sequencer = theDXApplication->network->sequencer;
175     if (sequencer)
176 	sequencer->transmitted = FALSE;
177 
178     if (this->inExecOnChange())
179     {
180 	this->updateMacros(TRUE);
181 	this->resumeExecOnChange();
182     }
183     this->execOnChange 		= FALSE;	// Avoid a resumeExecOnChange()
184     this->endLastExecution(FALSE);
185 
186     this->forceNetworkResend 	= TRUE;
187     this->forceParameterResend 	= TRUE;
188     this->execOnChangeSuspensions = 0;
189     this->isCurrentlyExecuting  = FALSE;
190     this->vcrIsExecuting    	= FALSE;
191 
192 }
193 
updateMacros(boolean force)194 void DXExecCtl::updateMacros(boolean force)
195 {
196     DXPacketIF *p = theDXApplication->getPacketIF();
197     if (p == NULL)
198 	return;
199     boolean forcenet   = force  || this->forceNetworkResend;
200     boolean forceparam = force  || this->forceParameterResend;
201 
202     boolean resume = FALSE;
203 
204     if (this->inExecOnChange() AND !this->isExecOnChangeSuspended())
205     {
206         this->suspendExecOnChange();
207         resume = TRUE;
208     }
209 
210     this->forceNetworkResend = FALSE;
211     this->forceParameterResend = FALSE;
212 
213 #if WORKSPACE_PAGES
214     ProcessGroupManager *pmgr = (ProcessGroupManager*)
215 	theDXApplication->network->getGroupManagers()->findDefinition (PROCESS_GROUP);
216     if(pmgr AND pmgr->isDirty())
217 	pmgr->sendAssignment(ProcessGroupManager::ATTACH);
218 #else
219     if(theDXApplication->PGManager AND theDXApplication->PGManager->isDirty())
220           theDXApplication->PGManager->
221                 sendAssignment(ProcessGroupManager::ATTACH);
222 #endif
223 
224     ListIterator ii(theDXApplication->macroList);
225     Network *n;
226     while((n = (Network*)ii.getNext()) != NULL)
227     {
228 	boolean dirty = n->isDirty();
229 	if (forcenet || dirty)
230 	    n->sendNetwork();
231 	if (forceparam || dirty)
232 	    n->sendValues(forceparam);
233     }
234 
235     n = theDXApplication->network;
236     boolean dirty = n->isDirty();
237     if (forcenet || dirty)
238 	n->sendNetwork();
239     if (forceparam || dirty)
240 	n->sendValues(forceparam);
241 
242     SequencerNode* sequencer = n->sequencer;
243     if (sequencer && (force || NOT sequencer->transmitted))
244 	this->vcrTransmit();
245 
246     if (resume)
247 	this->resumeExecOnChange();
248 
249 }
250 
vcrFrameSet(char * command)251 void DXExecCtl::vcrFrameSet(char* command)
252 {
253     DXPacketIF *p = theDXApplication->getPacketIF();
254     void   (*callback)(void*,int,void*) = NULL;
255 
256     if (p != NULL)
257     {
258     	if(this->inExecOnChange())
259         {
260 	     this->suspendExecOnChange();
261 	     callback = ResumeExecOnChange;
262 	}
263 
264     	p->send(DXPacketIF::FOREGROUND, command, callback);
265     }
266 }
267 
vcrTransmit()268 void DXExecCtl::vcrTransmit()
269 {
270     char  command[1024];
271     DXPacketIF *p = theDXApplication->getPacketIF();
272     SequencerNode* vcr = theDXApplication->network->sequencer;
273 
274     if (p == NULL)
275    	return;
276 
277     sprintf(command, "sequence %s();\n",
278 		     theDXApplication->network->getNameString());
279     p->send(DXPacketIF::FOREGROUND, command);
280 
281     char *s = vcr->getFrameControlString();
282     p->send(DXPacketIF::FOREGROUND, s);
283     delete s;
284 
285     p->send(DXPacketIF::FOREGROUND,
286             vcr->isLoopMode() ? "loop on;\n" : "loop off;\n");
287 
288     p->send(DXPacketIF::FOREGROUND,
289             vcr->isPalindromeMode() ? "palindrome on;\n" : "palindrome off;\n");
290 
291     vcr->transmitted = TRUE;
292 
293 }
294 
vcrExecute(int action)295 void DXExecCtl::vcrExecute(int action)
296 {
297     SequencerNode* sequencer = theDXApplication->network->sequencer;
298     DXPacketIF *p = theDXApplication->getPacketIF();
299 
300     if (NOT p OR this->vcrIsExecuting OR this->isCurrentlyExecuting )
301     {
302 	SequencerDirection direction;
303 
304 	if(NOT p)
305 	    ErrorMessage("No Connection to the server.");
306 	else
307 	    ErrorMessage("The program is currently executing.");
308 
309 	if (action == VCR_FORWARD)
310 	    direction = (p AND this->vcrIsExecuting ?
311 				SequencerNode::BackwardDirection :
312 				SequencerNode::Directionless);
313 	else
314 	    direction = (p AND this->vcrIsExecuting ?
315 				SequencerNode::ForwardDirection :
316 				SequencerNode::Directionless);
317 
318 	sequencer->setPlayDirection(direction);
319 
320    	return;
321     }
322 
323     this->vcrIsExecuting = TRUE;
324     this->beginSingleExecution(TRUE); // May suspend ExecOnChange.
325 
326     p->send(DXPacketIF::FOREGROUND,
327 	    action==VCR_FORWARD ? "forward;\n" : "backward;\n");
328 
329     p->send(DXPacketIF::FOREGROUND, sequencer->isStepMode() ?
330 				    "step;\n" : "play;\n");
331 
332 }
333 
vcrCommand(int action,boolean pressed)334 void DXExecCtl::vcrCommand(int action, boolean pressed)
335 {
336     char  command[30];
337     DXPacketIF *p = theDXApplication->getPacketIF();
338     SequencerNode* sequencer = theDXApplication->network->sequencer;
339     Widget vcr = NULL;
340     boolean doEnd = FALSE;
341 
342     if (action == VCR_STOP) {
343 	ASSERT(sequencer);
344 	vcr = sequencer->getVCRWidget();
345     }
346 
347     if (p == NULL)
348     {
349 //	this->endLastExecution(!this->vcrIsExecuting);
350 	this->vcrIsExecuting = FALSE;
351         sequencer->setPlayDirection(SequencerNode::Directionless);
352 
353 	if (action == VCR_STOP)
354 	    XtVaSetValues(vcr, XmNnext, sequencer->next, NULL);
355 
356    	return;
357     }
358 
359     switch(action)
360     {
361 	 case VCR_PALINDROME:
362 	     sequencer->setPalindromeMode(pressed);
363 	     strcpy(command, pressed ? "palindrome on;\n" : "palindrome off;\n");
364 
365 	     break;
366 
367 	case VCR_STEP:
368 	     sequencer->setStepMode(pressed);
369 	     sequencer->setPlayDirection(SequencerNode::Directionless);
370 	     strcpy(command, "pause;\n");
371 	     doEnd = this->vcrIsExecuting;
372     	     this->vcrIsExecuting = FALSE;
373 
374 	     break;
375 
376 	case VCR_LOOP:
377 	     sequencer->setLoopMode(pressed);
378 	     strcpy(command, pressed ?  "loop on;\n" : "loop off;\n");
379 
380 	     break;
381 
382 	case VCR_PAUSE:
383 
384 	     strcpy(command, "pause;\n");
385 	     doEnd = this->vcrIsExecuting;
386     	     this->vcrIsExecuting = FALSE;
387 	     sequencer->setPlayDirection(SequencerNode::Directionless);
388 	     break;
389 
390 	case VCR_STOP:
391 
392 	     strcpy(command, "stop;\n");
393 	     doEnd = this->vcrIsExecuting;
394     	     this->vcrIsExecuting = FALSE;
395 	     sequencer->setPlayDirection(SequencerNode::Directionless);
396 
397 	     break;
398 
399 	default:
400 
401 	     ASSERT(FALSE);
402     }
403 
404     p->send(DXPacketIF::FOREGROUND,command);
405 
406     if (action == VCR_STOP)
407     {
408         sequencer->next = sequencer->getStartValue();
409         sprintf(command, "@nextframe = %d;\n", sequencer->next);
410     	if(this->inExecOnChange()
411 	   AND !this->isExecOnChangeSuspended())
412 	     this->suspendExecOnChange();
413         p->send(DXPacketIF::FOREGROUND, command, ResetVcrNextFrame);
414     }
415 
416     if (doEnd)
417 	this->endLastExecution(action != VCR_STOP);
418 }
419 
ResetVcrNextFrame(void * clientData,int id,void * p)420 void DXExecCtl::ResetVcrNextFrame(void *clientData, int id, void *p)
421 {
422     DXExecCtl *ctl = theDXApplication->getExecCtl();
423     SequencerNode* sequencer = theDXApplication->network->sequencer;
424     ASSERT(sequencer);
425     Widget vcr = sequencer->getVCRWidget();
426 
427     sequencer->next = sequencer->getStartValue();
428     XtVaSetValues(vcr, XmNnext, sequencer->next, NULL);
429 
430     if(ctl->isExecOnChangeSuspended())
431 	ctl->resumeExecOnChange();
432 }
433 
enableExecOnChange()434 void DXExecCtl::enableExecOnChange()
435 {
436     DXPacketIF *p = theDXApplication->getPacketIF();
437     if (!p || this->execOnChange)
438 	return;
439 
440     //
441     // Set the light green now, so that sending big networks looks like
442     // execution.
443     //
444     theDXApplication->notifyClients(DXApplication::MsgExecute);
445 
446     //
447     // Update macros here and not in beginSingleExecution() so that
448     // execOnChange doesn't get suspended.
449     //
450     this->updateMacros();
451     this->execOnChange = TRUE;
452 
453     //
454     // Go into exec on change mode.
455     //
456     this->resumeExecOnChange();
457 
458     //
459     // Do what is usually necessary at the beginning of an execution.
460     //
461     this->beginSingleExecution(FALSE);	// updateMacros done above
462 
463     //
464     // Now cause the first execution.
465     //
466     char s[100];
467     strcpy(s, theDXApplication->network->getNameString());
468     strcat(s, "();\n");
469     p->send(DXPacketIF::FOREGROUND, s, DXExecCtl::ExecComplete, NULL);
470 }
471 //
472 // Go out of execution on change mode without terminating the current
473 // graph execution.  If not current executing, then we go ahead and
474 // go out of eoc mode, otherwise schedule the exit from eoc mode for
475 // the end of the current graph execution (see endLastExecution()).
476 // We return TRUE if we were able to go out of eoc mode now, FALSE if
477 // we won't be going out until the end of the current execution.
478 //
endExecOnChange()479 boolean DXExecCtl::endExecOnChange()
480 {
481     if (!this->inExecOnChange())
482 	return TRUE;
483 
484     //
485     // If the exec is currently executing, then we will wait to go out
486     // of execute-on-change mode until the current execution completes.
487     // If we don't do this, then the INTERRUPT message to go out of
488     // execute on change, will also kill the current graph execution,
489     // which we don't want to do.
490     //
491     if (this->isCurrentlyExecuting) {
492 	this->endExecOnChangePending = TRUE;
493 	return FALSE;
494     }
495 
496     if (this->vcrIsExecuting) {
497 	this->vcrIsExecuting = FALSE;	// Only do one endLastExecution().
498         this->vcrCommand(VCR_PAUSE, 0);
499     }
500 
501     this->endExecOnChangePending = FALSE;
502     this->execOnChangeSuspensions = 0;
503     this->execOnChange = FALSE;
504     DXPacketIF *p = theDXApplication->getPacketIF();
505     if (p)
506 	p->send(DXPacketIF::INTERRUPT);
507 
508     theDXApplication->notifyClients(DXApplication::MsgExecuteDone);
509 
510     return TRUE;
511 
512 }
suspendExecOnChange()513 void DXExecCtl::suspendExecOnChange()
514 {
515     if (!this->inExecOnChange())
516 	return;
517 
518     if (this->execOnChangeSuspensions == 1)
519 	return;		// Already suspended
520 
521     this->execOnChangeSuspensions = 1;
522 
523     DXPacketIF *p = theDXApplication->getPacketIF();
524     if (p) {
525 	p->send(DXPacketIF::INTERRUPT);
526         p->sendImmediate("sync");
527     }
528 }
resumeExecOnChange()529 void DXExecCtl::resumeExecOnChange()
530 {
531 
532     this->execOnChangeSuspensions = 0;
533 #if 00
534     if (!this->inExecOnChange() || this->isExecuting())
535 	return;
536     DXPacketIF *p = theDXApplication->getPacketIF();
537     if (p == NULL)
538 	return;
539 #else
540     DXPacketIF *p = theDXApplication->getPacketIF();
541     if (p == NULL)
542 	return;
543 
544     if (!this->inExecOnChange())
545 	return;
546     if (this->isExecuting()) {
547 	this->resumeExecOnChangeAfterExecution = TRUE;
548         this->execOnChangeSuspensions = 1;
549 	return;
550     }
551 #endif
552 
553 
554     //
555     // Be sure that all pending assignments/definitions are processed by
556     // the executive before going into execute on change.  If we don't do
557     // this we can get multiple executions from the pending assigments.
558     // Note that this an unneeded '$sync' is sent when we are in execute-
559     // on-change and the user does an 'execute-once' command.  In this
560     // case we still send the '$sync', but it is not necessary.
561     //
562     p->sendImmediate("sync");
563 
564     char s[100];
565     strcpy(s, theDXApplication->network->getNameString());
566     strcat(s, "();\n");
567     p->send(DXPacketIF::BACKGROUND, s);
568     theDXApplication->notifyClients(DXApplication::MsgStandBy);
569 }
executeOnce()570 void DXExecCtl::executeOnce()
571 {
572     DXPacketIF *p = theDXApplication->getPacketIF();
573     if (p == NULL)
574 	return;
575 
576 #if 0
577     if (this->inExecOnChange())
578 	this->suspendExecOnChange();
579 #endif
580 
581     this->beginSingleExecution(TRUE);
582 
583     char s[100];
584     strcpy(s, theDXApplication->network->getNameString());
585     strcat(s, "();\n");
586     p->send(DXPacketIF::FOREGROUND, s, DXExecCtl::ExecComplete, NULL);
587 
588 }
terminateExecution()589 void DXExecCtl::terminateExecution()
590 {
591 #ifdef SET_HW_BUSY_CURSOR
592     if (this->hwExecuting > 0 AND NOT this->hwBusy) {
593 	theDXApplication->setBusyCursor(TRUE);
594 	this->hwBusy = TRUE;
595     }
596 #endif
597 
598     if (!this->isCurrentlyExecuting && !this->execOnChange)
599 	return;
600 
601     if (this->vcrIsExecuting) {
602 	this->vcrIsExecuting = FALSE;	// Only do one endLastExecution().
603         this->vcrCommand(VCR_PAUSE, 0);
604     }
605 
606     Symbol msg;
607     DXPacketIF *p = theDXApplication->getPacketIF();
608     if (p == NULL) {
609 	msg = DXApplication::MsgExecuteDone;
610         //
611         // Set activation of execution dependent commands.
612         //
613         theDXApplication->notExecutingCmd->execute();
614     } else {
615 	msg = 0;
616 	p->send(DXPacketIF::INTERRUPT);
617 	p->send(DXPacketIF::FOREGROUND, "Executive(\"nop\");",
618 				DXExecCtl::ExecComplete, NULL);
619         p->sendImmediate("sync");
620 	theDXApplication->executeOnChangeCmd->activate();
621     }
622 
623     this->execOnChange = FALSE;
624     // FIXME: should use the following but won't right before release...
625     this->isCurrentlyExecuting = FALSE;
626     if (msg)
627         theDXApplication->notifyClients(msg);
628 }
629 
updateMacro(Network * n)630 void DXExecCtl::updateMacro(Network *n)
631 {
632     DXPacketIF *p = theDXApplication->getPacketIF();
633     if (p == NULL)
634 	return;
635 
636     boolean resume = FALSE;
637 
638     if (n->isDirty())
639     {
640         if (this->inExecOnChange() AND !this->isExecOnChangeSuspended())
641         {
642             this->suspendExecOnChange();
643             resume = TRUE;
644         }
645 
646 	n->sendNetwork();
647 	n->sendValues();
648 
649 	if (resume)
650 	    this->resumeExecOnChange();
651     }
652 }
653 
654 //
655 // This function is called with a boolean that, in essence, indicates
656 // whether the system is quiescent (updateable) or active (i.e. as a
657 // result of the BG: begin message, and thus not updateable).
beginSingleExecution(boolean update)658 void DXExecCtl::beginSingleExecution(boolean update)
659 {
660     theDXApplication->notifyClients(DXApplication::MsgExecute);
661 
662     if (update && this->inExecOnChange() && !this->isExecOnChangeSuspended())
663 	this->suspendExecOnChange();
664 
665     theDXApplication->clearErrorList();
666 
667     if (update)
668 	this->updateMacros();
669 
670     this->isCurrentlyExecuting = TRUE;
671     //
672     // Set activation of execution dependent commands.
673     //
674     theDXApplication->executingCmd->execute();
675 
676 }
677 
endLastExecution(boolean resume)678 void DXExecCtl::endLastExecution(boolean resume)
679 {
680     this->isCurrentlyExecuting = FALSE;
681     SequencerNode* sequencer = theDXApplication->network->sequencer;
682     Symbol msg = 0;
683 
684     if (this->vcrIsExecuting)
685     {
686 	if (sequencer->isStepMode())
687 	    this->vcrIsExecuting = FALSE;
688     }
689 
690     if ((resume || this->resumeExecOnChangeAfterExecution) AND
691 	this->isExecOnChangeSuspended()) {
692 	this->resumeExecOnChange(); // This may result in MsgStandBy message
693     } else if (this->inExecOnChange() && !this->isExecOnChangeSuspended()) {
694 	if (this->hwExecuting <= 0)
695 	    msg = DXApplication::MsgStandBy;
696     }
697 
698     //
699     // If a request to exit ExecOnChange mode was requested during an
700     // execution, then do it now.
701     //
702     if (this->endExecOnChangePending) {
703 	this->endExecOnChangePending = FALSE;
704 	this->endExecOnChange();
705 	msg = 0;
706     }
707 
708     this->resumeExecOnChangeAfterExecution = FALSE;
709 
710     //
711     // Set activation of execution dependent commands.
712     //
713     theDXApplication->notExecutingCmd->execute();
714 
715     //
716     // Indicate the nodes that had errors.
717     // FIXME: only do this if there are errors.
718     //
719     theDXApplication->refreshErrorIndicators();
720 
721     if (msg)
722 	theDXApplication->notifyClients(msg);
723 }
724