Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtmail / dtmail / RoamInterruptibleCmd.C
1 /* $XConsortium: RoamInterruptibleCmd.C /main/3 1995/11/06 16:12:29 rswiston $ */
2 /*
3  *+SNOTICE
4  *
5  *      RESTRICTED CONFIDENTIAL INFORMATION:
6  *      
7  *      The information in this document is subject to special
8  *      restrictions in a confidential disclosure agreement bertween
9  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
10  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
11  *      Sun's specific written approval.  This documment and all copies
12  *      and derivative works thereof must be returned or destroyed at
13  *      Sun's request.
14  *
15  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
16  *
17  *+ENOTICE
18  */
19 ///////////////////////////////////////////////////////////////
20 // RoamInterruptibleCmd.C: Abstract class that supports lengthy,
21 //                     user-interruptible activities
22 //////////////////////////////////////////////////////////////
23 #include "RoamInterruptibleCmd.hh"
24 #include "DtMailWDM.hh"
25 #include "Application.h"
26 #include <Xm/Xm.h>
27 #include <Xm/MessageB.h>
28 #include <assert.h>
29 extern forceUpdate( Widget );
30
31
32 RoamInterruptibleCmd::RoamInterruptibleCmd ( char *name, 
33                                              char *label, 
34                                              int active ) :
35                         NoUndoCmd ( name, label, active )
36 {
37     _wpId        = NULL;   // There is no work procedure yet
38     _callback    = NULL;           // Callbacks are specified in execute()
39     _clientData  = NULL;
40     _done        = FALSE; 
41     _interrupted = FALSE;
42 }
43
44 RoamInterruptibleCmd::~RoamInterruptibleCmd()
45 {
46     // Clean up by removing all callbacks
47     
48     if ( _wpId)    
49         XtRemoveWorkProc ( _wpId );
50 }
51
52 void 
53 RoamInterruptibleCmd::execute ( 
54     RoamTaskDoneCallback callback, 
55     void *clientData
56 )
57 {
58     _callback   = callback;
59     _clientData = clientData;
60     execute();
61 }
62
63 void 
64 RoamInterruptibleCmd::execute()
65 {
66     char *name_str;
67     
68     name_str = (char *) name();
69
70     _done  = FALSE;  // Initialize flag
71
72     // Let the derived class post the dialog.
73     // Updates happen when derived classes call update() or 
74     // updateMessage().
75
76     post_dialog();
77     
78     // Call the Cmd execute function to handle the Undo, and other
79     // general mechanisms supported by Cmd. 
80     // execute() calls doit() of derived class.
81     
82     Cmd::execute();  
83
84     // If the task was completed in a single call,
85     // don't bother to set up a work procedure. Just
86     // give derived classes a chance to cleanup and
87     // call the application's callback function
88
89     // If it was interrupted, the interruptCallback would have been
90     // called already and the dialog would have been unposted...
91
92     // We need to focus on only two cases here:  what if the task was
93     // was completed in one call without interruptions (unpost dialog 
94     // and call callback indicating task completed), and what if the 
95     // task was not completed in one call (install a workProc...)
96     // 
97
98     // if it done but not interrupted, it was genuinely done.
99     if (_done && !_interrupted)
100       {
101           unpost_dialog();  // derived classes implement this
102           cleanup();
103           
104           if ( _callback )  // the FALSE is to say it was not interrupted.
105               ( *_callback )( this, FALSE, _clientData );
106       }
107
108     // If the task is not done and it was not interrupted and there is
109     // a callback to install, install a work procedure to continue the 
110     // task as soon as possible.  Call the callback via the work proc
111     // after completion.
112     // 
113     
114     else if ((!_done && !_interrupted && _callback)) 
115       {
116           
117           _wpId = XtAppAddWorkProc ( theApplication->appContext(), 
118                                   &RoamInterruptibleCmd::workProcCallback,
119                                   (XtPointer) this );
120       }
121 }
122
123 Boolean 
124 RoamInterruptibleCmd::workProcCallback ( 
125     XtPointer clientData 
126 )
127 {
128     RoamInterruptibleCmd *obj = (RoamInterruptibleCmd *) clientData;
129     
130     // The work procedure just returns the value returned by the
131     // workProc member function.
132     
133     return ( obj->workProc() );
134 }
135
136 Boolean 
137 RoamInterruptibleCmd::workProc()
138 {
139     // Call derived class's check_if_done() and see if they think the
140     // work is already done.
141
142      check_if_done();
143
144      if (_interrupted) {
145
146          unpost_dialog();
147          cleanup();
148
149         // the TRUE is to say task was interrupted
150
151         if ( _callback )  
152             ( *_callback )( this, TRUE, _clientData );
153      }   
154     
155     // If the task has been completed, hide the dialog,
156     // give the derived class a chance to clean up, and notify
157     // the application that instantiated this object.
158     
159     else if (_done) {
160         unpost_dialog();
161         cleanup();
162         
163         // the FALSE is to say task completed without interruptions
164
165         if ( _callback )  
166             ( *_callback )( this, FALSE, _clientData );
167     }
168     
169     return _done;
170 }
171
172 void 
173 RoamInterruptibleCmd::cleanup()
174 {
175     // Empty
176 }
177
178 // The task has been interrupted.  The user clicked on interrupt...
179
180 void 
181 RoamInterruptibleCmd::interruptCallback ( 
182     void * clientData 
183 )
184 {
185     RoamInterruptibleCmd *obj = ( RoamInterruptibleCmd * ) clientData;
186     
187     // Just set the _interrupt flag to TRUE. The workProc() 
188     // function will notice the next time it is called
189     
190     obj->interrupt();
191 }
192
193 void 
194 RoamInterruptibleCmd::interrupt()
195 {
196     _interrupted = TRUE;
197
198     if (_wpId) {
199         // Remove the work procedure
200
201         XtRemoveWorkProc ( _wpId );
202     }
203     
204     // Remove the working dialog and give derived 
205     // classes a chance to clean up 
206     
207     unpost_dialog();
208     cleanup();
209     
210     // Notify the application that the task was interrupted
211     
212     if ( _callback )
213         ( *_callback )( this, TRUE, _clientData);
214 }
215
216 void 
217 RoamInterruptibleCmd::updateMessage ( 
218     char * msg 
219 )
220 {
221     theDtMailWDM->updateDialog ( msg );
222     forceUpdate(theDtMailWDM->baseWidget());
223 }
224
225 Boolean
226 RoamInterruptibleCmd::interrupted()
227 {
228     return _interrupted;
229 }
230
231 void
232 RoamInterruptibleCmd::update()
233 {
234     forceUpdate(theDtMailWDM->baseWidget());
235 }
236
237
238