233 lines
5.8 KiB
C
233 lines
5.8 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* @(#)$XConsortium: action.c /main/3 1996/05/07 13:57:56 drk $ */
|
|
|
|
#include <Xm/Xm.h>
|
|
#include <Dt/Dt.h>
|
|
#include <Dt/Action.h>
|
|
|
|
#include "xims.h"
|
|
|
|
static void DbReloadProc(/* cd */);
|
|
static bool init_action_env(/* */);
|
|
static void action_cb(long unsigned id, XtPointer cd,
|
|
DtActionArg *args, int argcnt, DtActionStatus status);
|
|
static void wait_action_done(/* */);
|
|
|
|
static bool actionEnabled = False;
|
|
static int actionDone = True;
|
|
static int actionErr = NoError;
|
|
static DtActionInvocationID actionId = 0;
|
|
|
|
|
|
/* ***** DtAction functions ***** */
|
|
|
|
static void DbReloadProc(XtPointer cd)
|
|
{
|
|
DPR(("DbReloadProc(): action database updated\n"));
|
|
DtDbLoad(); /* Pick up any dynamic changes to the database files */
|
|
}
|
|
|
|
static bool init_action_env(void)
|
|
{
|
|
init_window_env();
|
|
|
|
if (actionEnabled != True) {
|
|
|
|
if (DtAppInitialize(appC, Dpy, TopW, Wargv[0], DTIMS_CLASS) == False) {
|
|
/* DtInitialize() has already logged an appropriate error msg */
|
|
return False;
|
|
}
|
|
DtDbLoad(); /* Load the filetype/action databases */
|
|
DtDbReloadNotify(DbReloadProc, NULL);
|
|
|
|
actionEnabled = True;
|
|
}
|
|
|
|
return actionEnabled;
|
|
}
|
|
|
|
static void action_cb(long unsigned id, XtPointer cd /* unused */,
|
|
DtActionArg *args, int argcnt, DtActionStatus status)
|
|
{
|
|
if (actionId == 0) {
|
|
DPR(("action_cb(): invalid id %d != %d\n", id, actionId));
|
|
return;
|
|
}
|
|
if (id != actionId) {
|
|
DPR(("action_cb(): invalid id %d != %d\n", id, actionId));
|
|
return;
|
|
}
|
|
|
|
switch ((DtActionStatus) status) {
|
|
case DtACTION_INVOKED:
|
|
DPR((" ACTION_INVOKED\n"));
|
|
break;
|
|
|
|
case DtACTION_DONE:
|
|
DPR((" ACTION_DONE\n"));
|
|
actionId = 0;
|
|
actionDone = True;
|
|
break;
|
|
|
|
case DtACTION_CANCELED:
|
|
case DtACTION_FAILED:
|
|
DPR((" ACTION_%sED\n",
|
|
(status == DtACTION_CANCELED) ? "CANCEL" : "FAIL"));
|
|
if (args && argcnt > 0) {
|
|
int i;
|
|
for (i = 0; i < argcnt; i++) {
|
|
if (args[i].argClass == DtACTION_FILE) {
|
|
XtFree(args[i].u.file.name);
|
|
} else if (args[i].argClass == DtACTION_BUFFER) {
|
|
XtFree(args[i].u.buffer.bp);
|
|
XtFree(args[i].u.buffer.type);
|
|
XtFree(args[i].u.buffer.name);
|
|
}
|
|
}
|
|
XtFree((void *)args);
|
|
}
|
|
actionId = 0;
|
|
actionDone = False;
|
|
break;
|
|
|
|
case DtACTION_STATUS_UPDATE:
|
|
DPR((" ACTION_STATUS_UPDATE\n"));
|
|
actionDone = False;
|
|
break;
|
|
|
|
default: /* ignore */
|
|
DPR((" unknown status (%d)\n", status));
|
|
break;
|
|
}
|
|
|
|
if (actionId == 0) { /* action done */
|
|
send_dtims_msg(WIN_ST_ACTION_DONE, actionDone ? NoError : ErrRemoteAction);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
static void wait_action_done(void)
|
|
{
|
|
XEvent event;
|
|
|
|
DPR(("wait_action_done(): Begin\n"));
|
|
|
|
if (actionId == 0) return;
|
|
|
|
XtSetSensitive(TopW, False);
|
|
XtAddEventHandler(TopW, NoEventMask, True, dtims_msg_proc, 0);
|
|
|
|
while (actionId != 0 || actionErr != NoError) {
|
|
XtAppNextEvent(appC, &event);
|
|
XtDispatchEvent(&event);
|
|
}
|
|
|
|
XtRemoveEventHandler(TopW, XtAllEvents, True, dtims_msg_proc, 0);
|
|
XtSetSensitive(TopW, True);
|
|
|
|
DPR(("wait_action_done(): End\n"));
|
|
return;
|
|
}
|
|
|
|
int invoke_action(char *action, char *host)
|
|
{
|
|
if (init_action_env() != True) return ErrInternal;
|
|
|
|
DPR(("invoke_action(%s): host=%s\n", action, host));
|
|
|
|
if (!action || !*action) return ErrInternal;
|
|
if (host && !*host) host = NULL;
|
|
|
|
setErrFunc(action);
|
|
|
|
#ifdef DEBUG
|
|
if (DtActionExists(action) != True) {
|
|
DPR(("invoke_action(%s): action not exists\n", action));
|
|
}
|
|
#endif
|
|
|
|
/* Invoke the specified action */
|
|
actionId = DtActionInvoke(TopW, action, NULL, 0,
|
|
NULL, host, NULL, False, action_cb, NULL);
|
|
|
|
DPR(("invoke_action(%s): actionId=%d\n", actionId));
|
|
|
|
wait_action_done();
|
|
|
|
return actionErr;
|
|
}
|
|
|
|
|
|
void send_dtims_msg(int msg, int errcode)
|
|
{
|
|
XEvent ev;
|
|
|
|
ev.xclient.type = ClientMessage;
|
|
ev.xclient.window = winEnv.atom_owner;
|
|
ev.xclient.message_type = winEnv.atom_status;
|
|
ev.xclient.format = 32;
|
|
ev.xclient.data.l[0] = msg;
|
|
ev.xclient.data.l[1] = errcode;
|
|
ev.xclient.data.l[2] = ev.xclient.data.l[3] = ev.xclient.data.l[4] = 0L;
|
|
|
|
XSendEvent(Dpy, XtWindow(TopW), False, NoEventMask, &ev);
|
|
}
|
|
|
|
void dtims_msg_proc(Widget w, XtPointer cd, XEvent *event,
|
|
Boolean *continue_dispatch /* never changed */)
|
|
{
|
|
XClientMessageEvent *ev = &event->xclient;
|
|
int msg, errcode;
|
|
|
|
DPR(("dtimsMessageProc()\n"));
|
|
|
|
if (event->type != ClientMessage) return;
|
|
if (ev->message_type != winEnv.atom_status && ev->format != 32) {
|
|
DPR(("\tinvalid type([%d]%s) or format(%d) -- ignored\n",
|
|
ev->message_type, XGetAtomName(Dpy, ev->message_type), ev->format));
|
|
return;
|
|
}
|
|
msg = (int)ev->data.l[0];
|
|
errcode = (int)ev->data.l[1];
|
|
|
|
switch (msg) {
|
|
case WIN_ST_REMOTE_CONF:
|
|
case WIN_ST_REMOTE_RUN:
|
|
actionId = 0;
|
|
|
|
case WIN_ST_ACTION_DONE:
|
|
DPR(("\tmsg=%d errcode=%d\n", msg, errcode));
|
|
actionErr = errcode;
|
|
break;
|
|
|
|
default:
|
|
DPR(("\tunknown msg value (%d) -- ignored\n", msg));
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|