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 libraries 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>
52 #include "dtinfo_start.h"
53 #include "dtinfo_start.opnums"
56 * Operation names, number of arguments and default action names
58 static const char * LOAD_INFO_LIB_STRING = "DtInfo_LoadInfoLib";
59 static const int LOAD_INFO_LIB_ARGS = 3;
60 static const char * LOAD_INFO_LIB_ACTION = "DtInfoStart";
62 static const char * SHOW_INFO_AT_LOC_STRING = "DtInfo_ShowInfoAtLoc";
63 static const int SHOW_INFO_AT_LOC_ARGS = 4;
64 static const char * SHOW_INFO_LIB_SECTION_ACTION = "DtInfoStartAtLoc";
69 static Widget top_level;
71 static XtAppContext app_context;
73 static const int time_out = 1000; /* milliseconds */
75 static const int SET_NUM = 1; /* message cat set number */
77 static const char * name = "DtInfo"; /* ptype name and Xt name */
80 * Forward declarations for static functions
82 static int InvokeAction (
85 const char * action_name,
90 static void ActionDoneCallback (
91 DtActionInvocationID id,
92 XtPointer client_data,
95 DtActionStatus status);
98 XtPointer client_data,
101 static Tt_status ConnectToMessageServer (
104 static void ReceiveMessage (
105 XtPointer client_data,
109 static void LogToolTalkError (
110 DtMsgLogType msg_type,
112 char * function_name,
113 Tt_status error_num);
114 static void DieFromToolTalkError (
130 XtSetLanguageProc (NULL, NULL, NULL);
132 _DtEnvControl (DT_ENV_SET);
134 XtToolkitInitialize ();
136 app_context = XtCreateApplicationContext ();
138 if (!(display = XtOpenDisplay (app_context, NULL, NULL, name,
139 NULL, 0, &argc, argv))) {
140 DtMsgLogMessage (argv[0], DtMsgLogError,
141 (char *) GETMESSAGE (SET_NUM, 7, "XtOpenDisplay() failed. Perhaps the DISPLAY environment\nvariable is not set or is invalid."));
146 * Create a minimalist application shell - needed by
149 XtSetArg (args[i], XtNallowShellResize, True); i++;
150 XtSetArg (args[i], XtNmappedWhenManaged, False); i++;
151 XtSetArg (args[i], XtNheight, 1); i++;
152 XtSetArg (args[i], XtNwidth, 1); i++;
154 top_level = XtAppCreateShell (argv[0],
156 topLevelShellWidgetClass,
161 XtRealizeWidget (top_level);
164 * Initialize the desktop
166 if (DtAppInitialize (app_context, display, top_level,
167 argv[0], (char *)name) == False) {
168 DtMsgLogMessage (argv[0], DtMsgLogError,
169 (char *) GETMESSAGE (SET_NUM, 8, "DtAppInitialize() failed. Perhaps the desktop environment\nis not properly installed."));
174 * Connect to the message server
176 status = ConnectToMessageServer (argv[0]);
177 if (TT_OK != status) {
181 * An error Message has already been logged.
183 errfmt = GETMESSAGE (2, 2,
184 "Could not connect to ToolTalk:\n%s\nExiting ...");
185 DieFromToolTalkError (top_level, errfmt, status);
189 * Load the datatypes and actions
193 XtAppMainLoop (app_context);
203 const char * action_name,
210 DtActionInvocationID action_id;
212 if (op_num == SHOW_INFO_AT_LOC)
215 args = (DtActionArg *) XtCalloc (num_args, sizeof (DtActionArg));
217 DtMsgLogMessage (prog_name, DtMsgLogError,
218 (char *) GETMESSAGE (SET_NUM, 6,
219 "Cannot invoke an action because malloc(1) failed."));
223 args[0].argClass = DtACTION_FILE;
224 args[0].u.file.name = info_lib;
226 if (op_num == SHOW_INFO_AT_LOC) {
227 args[1].argClass = DtACTION_BUFFER;
228 args[1].u.buffer.name = topic;
229 args[1].u.buffer.size = strlen (topic) + 1;
230 args[1].u.buffer.writable = False;
233 action_id = DtActionInvoke (top_level,
234 (char *) action_name,
241 (DtActionCallbackProc) ActionDoneCallback,
245 DtMsgLogMessage (prog_name, DtMsgLogError, "Invoked %s\n", action_name);
249 * The following test, comment and code are from:
250 * $TOP/dtaction/Main.c
252 * "Set up a timer if we didn't get a valid procId --
253 * since there will be no invocation update in that case."
256 XtAppAddTimeOut (app_context,
258 (XtTimerCallbackProc) Exit,
269 DtActionInvocationID id,
270 XtPointer client_data,
273 DtActionStatus status)
280 status_name = "DtACTION_DONE";
283 status_name = "DtACTION_DONE";
285 case DtACTION_INVOKED:
286 status_name = "DtACTION_DONE";
288 case DtACTION_FAILED:
289 status_name = "DtACTION_DONE";
291 case DtACTION_CANCELED:
292 status_name = "DtACTION_DONE";
294 case DtACTION_INVALID_ID:
295 status_name = "DtACTION_DONE";
297 case DtACTION_STATUS_UPDATE:
298 status_name = "DtACTION_DONE";
301 status_name = "UNKNOWN";
309 DtMsgLogMessage ("dtinfo_start", DtMsgLogError,
310 "Action returned %s\n", status_name);
312 XtAppAddTimeOut(app_context, 10 * time_out,
313 (XtTimerCallbackProc) Exit,
316 case DtACTION_INVOKED:
317 case DtACTION_FAILED:
318 case DtACTION_CANCELED:
319 case DtACTION_INVALID_ID:
320 case DtACTION_STATUS_UPDATE:
323 DtMsgLogMessage ("dtinfo_start", DtMsgLogError,
324 "Action returned %s\n", status_name);
326 XtAppAddTimeOut(app_context, 10 * time_out,
327 (XtTimerCallbackProc) Exit,
334 ConnectToMessageServer (
345 status = tt_pointer_error (procid);
346 if (status != TT_OK) {
347 LogToolTalkError (DtMsgLogError, prog_name,
353 status = tt_ptype_declare (name);
354 if (status != TT_OK) {
355 LogToolTalkError (DtMsgLogError, prog_name,
356 "tt_ptype_declare", status);
362 if ((tt_int_error (ttfd)) != TT_OK) {
363 LogToolTalkError (DtMsgLogError, prog_name,
369 XtAppAddInput (app_context, ttfd, (XtPointer) XtInputReadMask,
370 ReceiveMessage, (char *) prog_name);
372 status = tt_session_join (tt_default_session());
373 if ((tt_int_error (ttfd)) != TT_OK) {
374 LogToolTalkError (DtMsgLogError, prog_name,
375 "tt_session_join", status);
389 XtPointer client_data,
393 static int last_op_num = 0;
398 const char * action_name;
402 char * prog_name = (char *) client_data;
403 static char lang[200];
404 const char * op_name;
405 char * info_lib = NULL;
407 message = tt_message_receive();
409 /* from tt_message_receive(3), and after examining other TT clients */
410 if (message == 0) return;
412 if (tt_pointer_error (message) != TT_OK) {
413 LogToolTalkError (DtMsgLogError, prog_name,
414 "tt_message_receive",
415 tt_pointer_error (message));
419 op_num = tt_message_opnum (message);
423 op_name = LOAD_INFO_LIB_STRING;
426 case SHOW_INFO_AT_LOC:
427 op_name = SHOW_INFO_AT_LOC_STRING;
432 * Don't know how I got this message
434 DtMsgLogMessage (prog_name, DtMsgLogError,
435 (char *) GETMESSAGE (SET_NUM, 11, "The message operation '%d' is not supported."),
438 tt_message_reject (message);
439 tt_message_destroy(message);
445 * Check the number of arguments
447 num_args = tt_message_args_count (message);
448 if ((op_num == LOAD_INFO_LIB && num_args != LOAD_INFO_LIB_ARGS) ||
449 (op_num == SHOW_INFO_AT_LOC && num_args != SHOW_INFO_AT_LOC_ARGS)) {
451 DtMsgLogMessage (prog_name, DtMsgLogError,
452 (char *) GETMESSAGE (SET_NUM, 12, "Message '%s' does not have the required\nnumber of arguments '%d'."),
454 (op_num == LOAD_INFO_LIB) ?
455 LOAD_INFO_LIB_ARGS : SHOW_INFO_AT_LOC_ARGS);
456 tt_message_reject (message);
457 tt_message_destroy(message);
462 * Check for an info lib
464 info_lib = tt_message_file (message);
465 if ((tt_ptr_error (info_lib) != TT_OK) || info_lib == NULL) {
467 * Use DTINFOLIBDEFAULT if it is defined
469 if ((info_lib = getenv ("DTINFOLIBDEFAULT")) == NULL) {
470 DtMsgLogMessage (prog_name, DtMsgLogError,
471 (char *) GETMESSAGE (SET_NUM, 10, "An InfoLib was not provided in the '%s' message\nand the environment variable DTINFOLIBDEFAULT was not defined."),
477 if ((action_name = tt_message_arg_val (message, 0)) == NULL) {
479 action_name = (op_num == LOAD_INFO_LIB) ?
480 LOAD_INFO_LIB_ACTION : SHOW_INFO_LIB_SECTION_ACTION;
482 DtMsgLogMessage (prog_name, DtMsgLogWarning,
483 (char *) GETMESSAGE (SET_NUM, 13, "Message '%s' specified a NULL action name.\nAction '%s' will be invoked."),
488 if ((exec_host = tt_message_arg_val (message, 1)) == NULL) {
490 DtMsgLogMessage (prog_name, DtMsgLogWarning,
491 (char *) GETMESSAGE (SET_NUM, 14, "Message '%s' specified a NULL execution host."),
495 if ((locale = tt_message_arg_val (message, 2)) == NULL) {
497 DtMsgLogMessage (prog_name, DtMsgLogWarning,
498 (char *) GETMESSAGE (SET_NUM, 15, "Message '%s' specified a NULL locale."),
503 * Put locale into the environment so that DtActionInvoke
504 * will propagate it to the dtinfo process.
506 (void) snprintf (lang, sizeof(lang), "LANG=%s", locale);
507 (void) putenv (lang);
510 if (op_num == SHOW_INFO_AT_LOC) {
511 if ((topic = tt_message_arg_val (message, 3)) == NULL) {
513 DtMsgLogMessage (prog_name, DtMsgLogError,
514 (char *) GETMESSAGE (SET_NUM, 16, "Message '%s' specified a NULL topic."),
520 if (op_num == last_op_num)
523 DtMsgLogMessage("dtinfo_start", DtMsgLogError,
524 "Received a duplicate tooltalk message: %s",
525 (op_num == LOAD_INFO_LIB) ?
526 "LOAD_INFO_LIB" : "SHOW_INFO_AT_LOC" );
533 "dtinfo_start", DtMsgLogError,
534 "Received a tooltalk message: %s\nInvoking action %s",
535 (op_num==LOAD_INFO_LIB) ? "LOAD_INFO_LIB" : "SHOW_INFO_AT_LOC",
538 last_op_num = op_num;
539 opstatus = InvokeAction (prog_name,
546 tt_message_fail (message);
551 tt_message_reply (message);
553 tt_message_destroy(message);
559 DtMsgLogType msg_type,
561 char * function_name,
565 message = tt_status_message(error_num);
566 DtMsgLogMessage (prog_name, msg_type, "%s: %s", function_name, message);
569 #define GETXMSTRING(s, m, d) XmStringCreateLocalized(GETMESSAGE(s,m,d))
572 ExitCB (Widget dialog, XtPointer client_data, XtPointer call_data)
574 exit((size_t) client_data);
578 DieFromToolTalkError(Widget parent, char *errfmt, Tt_status status)
581 Widget dialog, dialogShell;
582 char *errmsg, *statmsg;
583 XmString xms_errmsg, xms_ok, xms_title;
586 if (! tt_is_err(status)) return;
588 statmsg = tt_status_message(status);
589 errmsglen = strlen(errfmt) + strlen(statmsg) + 2;
590 errmsg = XtMalloc(errmsglen);
591 snprintf(errmsg, errmsglen, errfmt, statmsg);
593 xms_ok = GETXMSTRING(2, 3, "OK");
594 xms_errmsg = XmStringCreateLocalized(errmsg);
595 xms_title = GETXMSTRING(2, 1, "Dtinfo: Error");
598 XtSetArg(args[n], XmNautoUnmanage, False); n++;
599 XtSetArg(args[n], XmNokLabelString, xms_ok); n++;
600 XtSetArg(args[n], XmNdialogTitle, xms_title); n++;
601 XtSetArg(args[n], XmNmessageString, xms_errmsg); n++;
602 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
604 dialog = XmCreateErrorDialog(parent, "DtinfoStartError", args, n);
605 XtAddCallback(dialog, XmNokCallback, ExitCB, (XtPointer) status);
606 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
607 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
610 * Disable the frame menu from dialog since we don't want the user
611 * to be able to close dialogs with the frame menu
613 dialogShell = XtParent(dialog);
615 XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU); n++;
616 XtSetValues(dialogShell, args, n);
617 XtManageChild(dialog);
618 XtRealizeWidget(dialogShell);
621 XmStringFree(xms_ok);
622 XmStringFree(xms_errmsg);
623 XmStringFree(xms_title);
626 XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll);
632 XtPointer client_data,
636 * The following code to determine if DtActionInvoke
637 * resulted in the posting a dialog is from:
638 * $TOP/dtaction/Main.c
640 if (top_level->core.num_popups == 0)
643 XtAppAddTimeOut (app_context,
645 (XtTimerCallbackProc) Exit,