Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtmail / MotifApp / InterruptibleCmd.C
1 /* $XConsortium: InterruptibleCmd.C /main/3 1995/11/06 16:00:32 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 //////////////////////////////////////////////////////////////////////////////
21 //         This example code is from the book:
22 //
23 //           Object-Oriented Programming with C++ and OSF/Motif
24 //         by
25 //           Douglas Young
26 //           Prentice Hall, 1992
27 //           ISBN 0-13-630252-1 
28 //
29 //         Copyright 1991 by Prentice Hall
30 //         All Rights Reserved
31 //
32 //  Permission to use, copy, modify, and distribute this software for 
33 //  any purpose except publication and without fee is hereby granted, provided 
34 //  that the above copyright notice appear in all copies of the software.
35 ///////////////////////////////////////////////////////////////////////////////
36 //////////////////////////////////////////////////////////////////////////////
37
38
39 ///////////////////////////////////////////////////////////////
40 // InterruptibleCmd.C: Abstract class that supports lengthy,
41 //                     user-interruptible activities
42 //////////////////////////////////////////////////////////////
43 #include "InterruptibleCmd.h"
44 #include "WorkingDialogManager.h"
45 #include "Application.h"
46 #include <Xm/Xm.h>
47 #include <Xm/MessageB.h>
48 #include <assert.h>
49 extern forceUpdate( Widget );
50 InterruptibleCmd::InterruptibleCmd ( char *name, char *label, int active ) :
51                         NoUndoCmd ( name, label, active )
52 {
53     _wpId        = NULL;   // There is no work procedure yet
54     _callback    = NULL;           // Callbacks are specified in execute()
55     _clientData  = NULL;
56     _done        = FALSE; 
57 }
58
59 InterruptibleCmd::~InterruptibleCmd()
60 {
61     // Clean up by removing all callbacks
62     
63     if ( _wpId)    
64         XtRemoveWorkProc ( _wpId );
65 }
66
67 void InterruptibleCmd::execute ( TaskDoneCallback callback, void *clientData )
68 {
69     _callback   = callback;
70     _clientData = clientData;
71     execute();
72 }
73
74 void InterruptibleCmd::execute()
75 {
76     char *name_str;
77     char *label_str;
78     
79     name_str = (char *) name();
80     label_str = (char *) getLabel();
81
82     _done  = FALSE;  // Initialize flag
83     
84     // Call the Cmd execute function to handle the Undo, and other
85     // general mechanisms supported by Cmd. Execute calls doit()
86     
87     Cmd::execute();  
88     
89     // If the task was completed in a single call,
90     // don't bother to set up a work procedure. Just
91     // give derived classes a chance to cleanup and
92     // call the application's callback function
93     
94     if ( _done )
95     {
96         cleanup();
97         
98         if ( _callback )
99             ( *_callback )( this, FALSE, _clientData );
100     }
101     
102     // If the task is not done, post a WorkingDialog and 
103     // install a work procedure to continue the task 
104     // as soon as possible.
105     
106     if ( !_done )
107     {
108         theWorkingDialogManager->post (label_str,
109                                        "Fetching" , 
110                                        (void *) this,
111                                        NULL, 
112                                        &InterruptibleCmd::interruptCallback );
113         
114         _wpId = XtAppAddWorkProc ( theApplication->appContext(), 
115                                   &InterruptibleCmd::workProcCallback,
116                                   (XtPointer) this );
117     }
118 }
119
120 Boolean InterruptibleCmd::workProcCallback ( XtPointer clientData )
121 {
122     InterruptibleCmd *obj = (InterruptibleCmd *) clientData;
123     
124     // The work procedure just returns the value returned by the
125     // workProc member function.
126     
127     return ( obj->workProc() );
128 }
129
130 Boolean InterruptibleCmd::workProc()
131 {
132     doit();
133     
134     // If the task has been completed, hide the dialog,
135     // give the derived class a chance to clean up, and notify
136     // the application that instantiated this object.
137     
138     if ( _done )
139     {
140         theWorkingDialogManager->unpost();
141         cleanup();
142         
143         if ( _callback )
144             ( *_callback )( this, FALSE, _clientData );
145     }
146     
147     return _done;
148 }
149
150 void InterruptibleCmd::cleanup()
151 {
152     // Empty
153 }
154
155 void InterruptibleCmd::interruptCallback ( void * clientData )
156 {
157     InterruptibleCmd *obj = ( InterruptibleCmd * ) clientData;
158     
159     // Just set the _interrupt flag to TRUE. The workProc() 
160     // function will notice the next time it is called
161     
162     obj->interrupt();
163 }
164
165 void InterruptibleCmd::interrupt()
166 {
167     // Remove the work procedure
168     
169     XtRemoveWorkProc ( _wpId );
170     
171     // Remove the working dialog and give derived 
172     // classes a chance to clean up 
173     
174     theWorkingDialogManager->unpost();
175     cleanup();
176     
177     // Notify the application that the task was interrupted
178     
179     if ( _callback )
180         ( *_callback )( this, TRUE, _clientData);
181 }
182
183 void InterruptibleCmd::updateMessage ( char * msg )
184 {
185     theWorkingDialogManager->updateMessage ( msg );   
186 }