2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $TOG: dtinfo_start.c /main/9 1999/09/20 13:26:59 mgreess $
25 * (c) Copyright 1996 Digital Equipment Corporation.
26 * (c) Copyright 1996 Hewlett-Packard Company.
27 * (c) Copyright 1996 International Business Machines Corp.
28 * (c) Copyright 1996 Sun Microsystems, Inc.
29 * (c) Copyright 1996 Novell, Inc.
30 * (c) Copyright 1996 FUJITSU LIMITED.
31 * (c) Copyright 1996 Hitachi.
33 * This file contains the main program for: dtinfo_start
39 #include <X11/Intrinsic.h>
44 #include <Dt/EnvControlP.h>
45 #include <Dt/Action.h>
46 #include <Dt/DtGetMessageP.h>
47 #include <Dt/MsgLog.h>
51 #include "dtinfo_start.h"
52 #include "dtinfo_start.opnums"
55 * Operation names, number of arguments and default action names
57 static const char * LOAD_INFO_LIB_STRING = "DtInfo_LoadInfoLib";
58 static const int LOAD_INFO_LIB_ARGS = 3;
59 static const char * LOAD_INFO_LIB_ACTION = "DtInfoStart";
61 static const char * SHOW_INFO_AT_LOC_STRING = "DtInfo_ShowInfoAtLoc";
62 static const int SHOW_INFO_AT_LOC_ARGS = 4;
63 static const char * SHOW_INFO_LIB_SECTION_ACTION = "DtInfoStartAtLoc";
68 static Widget top_level;
70 static XtAppContext app_context;
72 static const int time_out = 1000; /* milliseconds */
74 static const int SET_NUM = 1; /* message cat set number */
76 static const char * name = "DtInfo"; /* ptype name and Xt name */
79 * Forward declarations for static functions
81 static int InvokeAction (
84 const char * action_name,
89 static void ActionDoneCallback (
90 DtActionInvocationID id,
91 XtPointer client_data,
94 DtActionStatus status);
97 XtPointer client_data,
100 static Tt_status ConnectToMessageServer (
103 static void ReceiveMessage (
104 XtPointer client_data,
108 static void LogToolTalkError (
109 DtMsgLogType msg_type,
111 char * function_name,
112 Tt_status error_num);
113 static void DieFromToolTalkError (
129 XtSetLanguageProc (NULL, NULL, NULL);
131 _DtEnvControl (DT_ENV_SET);
133 XtToolkitInitialize ();
135 app_context = XtCreateApplicationContext ();
137 if (!(display = XtOpenDisplay (app_context, NULL, NULL, name,
138 NULL, 0, &argc, argv))) {
139 DtMsgLogMessage (argv[0], DtMsgLogError,
140 (char *) GETMESSAGE (SET_NUM, 7, "XtOpenDisplay() failed. Perhaps the DISPLAY environment\nvariable is not set or is invalid."));
145 * Create a minimalist application shell - needed by
148 XtSetArg (args[i], XtNallowShellResize, True); i++;
149 XtSetArg (args[i], XtNmappedWhenManaged, False); i++;
150 XtSetArg (args[i], XtNheight, 1); i++;
151 XtSetArg (args[i], XtNwidth, 1); i++;
153 top_level = XtAppCreateShell (argv[0],
155 topLevelShellWidgetClass,
160 XtRealizeWidget (top_level);
163 * Initialize the desktop
165 if (DtAppInitialize (app_context, display, top_level, argv[0], name)
167 DtMsgLogMessage (argv[0], DtMsgLogError,
168 (char *) GETMESSAGE (SET_NUM, 8, "DtAppInitialize() failed. Perhaps the desktop environment\nis not properly installed."));
173 * Connect to the message server
175 status = ConnectToMessageServer (argv[0]);
176 if (TT_OK != status) {
180 * An error Message has already been logged.
182 errfmt = GETMESSAGE (2, 2,
183 "Could not connect to ToolTalk:\n%s\nExiting ...");
184 DieFromToolTalkError (top_level, errfmt, status);
188 * Load the datatypes and actions
192 XtAppMainLoop (app_context);
200 const char * action_name,
207 DtActionInvocationID action_id;
209 if (op_num == SHOW_INFO_AT_LOC)
212 args = (DtActionArg *) XtCalloc (num_args, sizeof (DtActionArg));
214 DtMsgLogMessage (prog_name, DtMsgLogError,
215 (char *) GETMESSAGE (SET_NUM, 6,
216 "Cannot invoke an action because malloc(1) failed."));
220 args[0].argClass = DtACTION_FILE;
221 args[0].u.file.name = info_lib;
223 if (op_num == SHOW_INFO_AT_LOC) {
224 args[1].argClass = DtACTION_BUFFER;
225 args[1].u.buffer.name = topic;
226 args[1].u.buffer.size = strlen (topic) + 1;
227 args[1].u.buffer.writable = False;
230 action_id = DtActionInvoke (top_level,
231 (char *) action_name,
238 (DtActionCallbackProc) ActionDoneCallback,
242 DtMsgLogMessage (prog_name, DtMsgLogError, "Invoked %s\n", action_name);
246 * The following test, comment and code are from:
247 * $TOP/dtaction/Main.c
249 * "Set up a timer if we didn't get a valid procId --
250 * since there will be no invocation update in that case."
253 XtAppAddTimeOut (app_context,
255 (XtTimerCallbackProc) Exit,
266 DtActionInvocationID id,
267 XtPointer client_data,
270 DtActionStatus status)
277 status_name = "DtACTION_DONE";
280 status_name = "DtACTION_DONE";
282 case DtACTION_INVOKED:
283 status_name = "DtACTION_DONE";
285 case DtACTION_FAILED:
286 status_name = "DtACTION_DONE";
288 case DtACTION_CANCELED:
289 status_name = "DtACTION_DONE";
291 case DtACTION_INVALID_ID:
292 status_name = "DtACTION_DONE";
294 case DtACTION_STATUS_UPDATE:
295 status_name = "DtACTION_DONE";
298 status_name = "UNKNOWN";
306 DtMsgLogMessage ("dtinfo_start", DtMsgLogError,
307 "Action returned %s\n", status_name);
309 XtAppAddTimeOut(app_context, 10 * time_out,
310 (XtTimerCallbackProc) Exit,
313 case DtACTION_INVOKED:
314 case DtACTION_FAILED:
315 case DtACTION_CANCELED:
316 case DtACTION_INVALID_ID:
317 case DtACTION_STATUS_UPDATE:
320 DtMsgLogMessage ("dtinfo_start", DtMsgLogError,
321 "Action returned %s\n", status_name);
323 XtAppAddTimeOut(app_context, 10 * time_out,
324 (XtTimerCallbackProc) Exit,
331 ConnectToMessageServer (
342 status = tt_pointer_error (procid);
343 if (status != TT_OK) {
344 LogToolTalkError (DtMsgLogError, prog_name,
350 status = tt_ptype_declare (name);
351 if (status != TT_OK) {
352 LogToolTalkError (DtMsgLogError, prog_name,
353 "tt_ptype_declare", status);
359 if ((tt_int_error (ttfd)) != TT_OK) {
360 LogToolTalkError (DtMsgLogError, prog_name,
366 XtAppAddInput (app_context, ttfd, (XtPointer) XtInputReadMask,
367 ReceiveMessage, (char *) prog_name);
369 status = tt_session_join (tt_default_session());
370 if ((tt_int_error (ttfd)) != TT_OK) {
371 LogToolTalkError (DtMsgLogError, prog_name,
372 "tt_session_join", status);
386 XtPointer client_data,
390 static int last_op_num = 0;
395 const char * action_name;
399 char * prog_name = (char *) client_data;
400 static char lang[200];
401 const char * op_name;
402 char * info_lib = NULL;
404 message = tt_message_receive();
406 /* from tt_message_receive(3), and after examining other TT clients */
407 if (message == 0) return;
409 if (tt_pointer_error (message) != TT_OK) {
410 LogToolTalkError (DtMsgLogError, prog_name,
411 "tt_message_receive",
412 tt_pointer_error (message));
416 op_num = tt_message_opnum (message);
420 op_name = LOAD_INFO_LIB_STRING;
423 case SHOW_INFO_AT_LOC:
424 op_name = SHOW_INFO_AT_LOC_STRING;
429 * Don't know how I got this message
431 DtMsgLogMessage (prog_name, DtMsgLogError,
432 (char *) GETMESSAGE (SET_NUM, 11, "The message operation '%d' is not supported."),
435 tt_message_reject (message);
436 tt_message_destroy(message);
442 * Check the number of arguments
444 num_args = tt_message_args_count (message);
445 if ((op_num == LOAD_INFO_LIB && num_args != LOAD_INFO_LIB_ARGS) ||
446 (op_num == SHOW_INFO_AT_LOC && num_args != SHOW_INFO_AT_LOC_ARGS)) {
448 DtMsgLogMessage (prog_name, DtMsgLogError,
449 (char *) GETMESSAGE (SET_NUM, 12, "Message '%s' does not have the required\nnumber of arguments '%d'."),
451 (op_num == LOAD_INFO_LIB) ?
452 LOAD_INFO_LIB_ARGS : SHOW_INFO_AT_LOC_ARGS);
453 tt_message_reject (message);
454 tt_message_destroy(message);
459 * Check for an info lib
461 info_lib = tt_message_file (message);
462 if ((tt_ptr_error (info_lib) != TT_OK) || info_lib == NULL) {
464 * Use DTINFOLIBDEFAULT if it is defined
466 if ((info_lib = getenv ("DTINFOLIBDEFAULT")) == NULL) {
467 DtMsgLogMessage (prog_name, DtMsgLogError,
468 (char *) GETMESSAGE (SET_NUM, 10, "An InfoLib was not provided in the '%s' message\nand the environment variable DTINFOLIBDEFAULT was not defined."),
474 if ((action_name = tt_message_arg_val (message, 0)) == NULL) {
476 action_name = (op_num == LOAD_INFO_LIB) ?
477 LOAD_INFO_LIB_ACTION : SHOW_INFO_LIB_SECTION_ACTION;
479 DtMsgLogMessage (prog_name, DtMsgLogWarning,
480 (char *) GETMESSAGE (SET_NUM, 13, "Message '%s' specified a NULL action name.\nAction '%s' will be invoked."),
485 if ((exec_host = tt_message_arg_val (message, 1)) == NULL) {
487 DtMsgLogMessage (prog_name, DtMsgLogWarning,
488 (char *) GETMESSAGE (SET_NUM, 14, "Message '%s' specified a NULL execution host."),
492 if ((locale = tt_message_arg_val (message, 2)) == NULL) {
494 DtMsgLogMessage (prog_name, DtMsgLogWarning,
495 (char *) GETMESSAGE (SET_NUM, 15, "Message '%s' specified a NULL locale."),
500 * Put locale into the environment so that DtActionInvoke
501 * will propagate it to the dtinfo process.
503 (void) sprintf (lang, "LANG=%s", locale);
504 (void) putenv (lang);
507 if (op_num == SHOW_INFO_AT_LOC) {
508 if ((topic = tt_message_arg_val (message, 3)) == NULL) {
510 DtMsgLogMessage (prog_name, DtMsgLogError,
511 (char *) GETMESSAGE (SET_NUM, 16, "Message '%s' specified a NULL topic."),
517 if (op_num == last_op_num)
520 DtMsgLogMessage("dtinfo_start", DtMsgLogError,
521 "Received a duplicate tooltalk message: %s",
522 (op_num == LOAD_INFO_LIB) ?
523 "LOAD_INFO_LIB" : "SHOW_INFO_AT_LOC" );
530 "dtinfo_start", DtMsgLogError,
531 "Received a tooltalk message: %s\nInvoking action %s",
532 (op_num==LOAD_INFO_LIB) ? "LOAD_INFO_LIB" : "SHOW_INFO_AT_LOC",
535 last_op_num = op_num;
536 opstatus = InvokeAction (prog_name,
543 tt_message_fail (message);
548 tt_message_reply (message);
550 tt_message_destroy(message);
556 DtMsgLogType msg_type,
558 char * function_name,
562 message = tt_status_message(error_num);
563 DtMsgLogMessage (prog_name, msg_type, "%s: %s", function_name, message);
566 #define GETXMSTRING(s, m, d) XmStringCreateLocalized(GETMESSAGE(s,m,d))
569 ExitCB (Widget dialog, XtPointer client_data, XtPointer call_data)
571 exit((size_t) client_data);
575 DieFromToolTalkError(Widget parent, char *errfmt, Tt_status status)
578 Widget dialog, dialogShell;
579 char *errmsg, *statmsg, *title;
580 XmString xms_errmsg, xms_ok, xms_title;
583 if (! tt_is_err(status)) return;
585 statmsg = tt_status_message(status);
586 errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
587 sprintf(errmsg, errfmt, statmsg);
589 xms_ok = GETXMSTRING(2, 3, "OK");
590 xms_errmsg = XmStringCreateLocalized(errmsg);
591 xms_title = GETXMSTRING(2, 1, "Dtinfo: Error");
594 XtSetArg(args[n], XmNautoUnmanage, False); n++;
595 XtSetArg(args[n], XmNokLabelString, xms_ok); n++;
596 XtSetArg(args[n], XmNdialogTitle, xms_title); n++;
597 XtSetArg(args[n], XmNmessageString, xms_errmsg); n++;
598 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
600 dialog = XmCreateErrorDialog(parent, "DtinfoStartError", args, n);
601 XtAddCallback(dialog, XmNokCallback, ExitCB, (XtPointer) status);
602 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
603 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
606 * Disable the frame menu from dialog since we don't want the user
607 * to be able to close dialogs with the frame menu
609 dialogShell = XtParent(dialog);
611 XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU); n++;
612 XtSetValues(dialogShell, args, n);
613 XtManageChild(dialog);
614 XtRealizeWidget(dialogShell);
617 XmStringFree(xms_ok);
618 XmStringFree(xms_errmsg);
619 XmStringFree(xms_title);
622 XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll);
628 XtPointer client_data,
632 * The following code to determine if DtActionInvoke
633 * resulted in the posting a dialog is from:
634 * $TOP/dtaction/Main.c
636 if (top_level->core.num_popups == 0)
639 XtAppAddTimeOut (app_context,
641 (XtTimerCallbackProc) Exit,