Link with C++ linker
[oweals/cde.git] / cde / programs / dtimsstart / action.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* @(#)$XConsortium: action.c /main/3 1996/05/07 13:57:56 drk $ */
24
25 #include        <Xm/Xm.h>
26 #include        <Dt/Dt.h>
27 #include        <Dt/Action.h>
28
29 #include        "xims.h"
30
31 static void     DbReloadProc(/* cd */);
32 static bool     init_action_env(/*  */);
33 static void     action_cb(DtActionInvocationID id, XtPointer cd,
34                           DtActionArg *args, int argcnt, int status);
35 static void     wait_action_done(/*  */);
36
37 static bool                     actionEnabled = False;
38 static int                      actionDone = True;
39 static int                      actionErr = NoError;
40 static DtActionInvocationID     actionId = 0;
41
42
43         /* *****  DtAction functions  ***** */
44
45 static void     DbReloadProc(cd)
46     XtPointer cd;
47 {
48     DPR(("DbReloadProc(): action database updated\n"));
49     DtDbLoad(); /* Pick up any dynamic changes to the database files */
50 }
51
52 static bool     init_action_env()
53 {
54     init_window_env();
55
56     if (actionEnabled != True) {
57
58         if (DtAppInitialize(appC, Dpy, TopW, Wargv[0], DTIMS_CLASS) == False) {
59                 /* DtInitialize() has already logged an appropriate error msg */
60             return False;
61         }
62         DtDbLoad();     /* Load the filetype/action databases */
63         DtDbReloadNotify(DbReloadProc, NULL);
64
65         actionEnabled = True;
66     }
67
68     return actionEnabled;
69 }
70
71 static void     action_cb(id, cd, args, argcnt, status)
72     DtActionInvocationID        id;
73     XtPointer   cd;     /* unused */
74     DtActionArg *args;
75     int         argcnt;
76     int         status;
77 {
78     if (actionId == 0) {
79         DPR(("action_cb(): invalid id %d != %d\n", id, actionId));
80         return;
81     }
82     if (id != actionId) {
83         DPR(("action_cb(): invalid id %d != %d\n", id, actionId));
84         return;
85     }
86
87     switch ((DtActionStatus) status) {
88         case DtACTION_INVOKED:
89             DPR(("  ACTION_INVOKED\n"));
90             break;
91
92         case DtACTION_DONE:
93             DPR(("  ACTION_DONE\n"));
94             actionId = 0;
95             actionDone = True;
96             break;
97
98         case DtACTION_CANCELED:
99         case DtACTION_FAILED:
100             DPR(("  ACTION_%sED\n",
101                 (status == DtACTION_CANCELED) ? "CANCEL" : "FAIL"));
102             if (args && argcnt > 0) {
103                 int     i;
104                 for (i = 0; i < argcnt; i++) {
105                     if (args[i].argClass == DtACTION_FILE) {
106                         XtFree(args[i].u.file.name);
107                     } else if (args[i].argClass == DtACTION_BUFFER) {
108                         XtFree(args[i].u.buffer.bp);
109                         XtFree(args[i].u.buffer.type);
110                         XtFree(args[i].u.buffer.name);
111                     }
112                 }
113                 XtFree((void *)args);
114             }
115             actionId = 0;
116             actionDone = False;
117             break;
118
119         case DtACTION_STATUS_UPDATE:
120             DPR(("  ACTION_STATUS_UPDATE\n"));
121             actionDone = False;
122             break;
123
124         default:        /* ignore */
125             DPR(("  unknown status (%d)\n", status));
126             break;
127     }
128
129     if (actionId == 0) {        /* action done */
130         send_dtims_msg(WIN_ST_ACTION_DONE, actionDone ? NoError : ErrRemoteAction);
131     }
132
133     return;
134 }
135
136
137 static void     wait_action_done()
138 {
139     XEvent event;
140
141     DPR(("wait_action_done(): Begin\n"));
142
143     if (actionId == 0)  return;
144
145     XtSetSensitive(TopW, False);
146     XtAddEventHandler(TopW, NoEventMask, True, dtims_msg_proc, 0);
147
148     while (actionId != 0 || actionErr != NoError) {
149         XtAppNextEvent(appC, &event);
150         XtDispatchEvent(&event);
151     }
152
153     XtRemoveEventHandler(TopW, XtAllEvents, True, dtims_msg_proc, 0);
154     XtSetSensitive(TopW, True);
155
156     DPR(("wait_action_done():  End\n"));
157     return;
158 }
159
160 int     invoke_action(action, host)
161     char        *action;
162     char        *host;
163 {
164     if (init_action_env() != True)      return ErrInternal;
165   
166     DPR(("invoke_action(%s): host=%s\n", action, host));
167
168     if (!action || !*action)    return ErrInternal;
169     if (host && !*host) host = NULL;
170
171     setErrFunc(action);
172
173 #ifdef  DEBUG
174     if (DtActionExists(action) != True) {
175         DPR(("invoke_action(%s): action not exists\n", action));
176     }
177 #endif
178
179     /* Invoke the specified action */
180     actionId = DtActionInvoke(TopW, action, NULL, 0,
181                 NULL, host, NULL, False, action_cb, NULL);
182
183     DPR(("invoke_action(%s): actionId=%d\n", actionId));
184
185     wait_action_done();
186
187     return actionErr;
188 }
189
190
191 void    send_dtims_msg(msg, errcode)
192     int msg, errcode;
193 {
194     XEvent ev;
195
196     ev.xclient.type = ClientMessage;
197     ev.xclient.window = winEnv.atom_owner;
198     ev.xclient.message_type = winEnv.atom_status;
199     ev.xclient.format = 32;
200     ev.xclient.data.l[0] = msg;
201     ev.xclient.data.l[1] = errcode;
202     ev.xclient.data.l[2] = ev.xclient.data.l[3] = ev.xclient.data.l[4] = 0L;
203
204     XSendEvent(Dpy, XtWindow(TopW), False, NoEventMask, &ev);
205 }
206
207 void    dtims_msg_proc(w, cd, event, continue_dispatch)
208     Widget w;
209     XtPointer cd;
210     XEvent *event;
211     Boolean *continue_dispatch; /* never changed */
212 {
213     XClientMessageEvent *ev = &event->xclient;
214     int msg, errcode;
215
216     DPR(("dtimsMessageProc()\n"));
217
218     if (event->type != ClientMessage)   return;
219     if (ev->message_type != winEnv.atom_status && ev->format != 32) {
220         DPR(("\tinvalid type([%d]%s) or format(%d) -- ignored\n",
221             ev->message_type, XGetAtomName(Dpy, ev->message_type), ev->format));
222         return;
223     }
224     msg = (int)ev->data.l[0];
225     errcode = (int)ev->data.l[1];
226
227     switch (msg) {
228         case WIN_ST_REMOTE_CONF: 
229         case WIN_ST_REMOTE_RUN: 
230                 actionId = 0;
231
232         case WIN_ST_ACTION_DONE:
233             DPR(("\tmsg=%d  errcode=%d\n", msg, errcode));
234             actionErr = errcode;
235             break;
236
237         default:
238             DPR(("\tunknown msg value (%d) -- ignored\n", msg));
239             break;
240     }
241     return;
242 }
243