#ifndef lint #ifdef sccs static char sccsid[] = "@(#)help.c 1.1 94/10/31 Copyright 1987 Sun Micro"; #endif #endif /* * Copyright (c) 1987 by Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include /* for callrpc2() */ #include /* for callrpc2() */ #include /* for callrpc2() */ #define HELPNAMELENGTH 256 #define HELPTEXTLINES 32 static short help_image[] = { #include }; mpr_static(help_request_icon, 64, 64, 1, help_image); static struct timeval timeout1 = { 5, 0 }; static struct timeval timeout2 = { 25, 0 }; static void help_request_default(); static void (*help_request_func)() = help_request_default; static void help_more_default(); static void (*help_more_func)(); static void help_set_server(); static char help_server_name[HELPNAMELENGTH]; static int help_request_seq; static void help_request_failed(window, data, str, why, event) Window window; char *data, *str, *why; Event *event; { char message[256]; if (data) { sprintf(message, "%s for %s.", str, data); } else { sprintf(message, "%s.", str); } alert_prompt(NULL, event, ALERT_POSITION, ALERT_SCREEN_CENTERED, ALERT_MESSAGE_STRINGS, message, 0, ALERT_BUTTON_YES, "OK", 0, HELP_DATA, why, 0); } /* * Default more help delivery function */ static void help_more_default(client, data, event) Window client; char *data; Event *event; { Help_request arg; char command[HELPNAMELENGTH+2]; int ret, callrpc2(); arg.data = data; if (event) { arg.x = event_x(event); arg.y = event_y(event); } arg.pid = getpid(); arg.seq = ++help_request_seq; if (help_server_name[0] == '\0') { /* Get server name from defaults database */ strncpy(help_server_name, defaults_get_string("/Help/Server", HELPDEFAULTSERVER, 0), HELPNAMELENGTH - 1); } if (callrpc2("localhost", HELPDEFAULTPROG, HELPVERS, HELPREQUEST, xdr_help, &arg, xdr_void, NULL, &timeout1)) { /* This fixes a bug where the user quits & restarts help servers */ /* between rpc calls. If this is the case, the second call should */ /* now go through: */ ret = callrpc2("localhost", HELPDEFAULTPROG, HELPVERS, HELPREQUEST, xdr_help, &arg, xdr_void, NULL, &timeout2); if (ret) { /* Request failed, spawn help server */ if (alert_prompt(NULL, NULL, ALERT_POSITION, ALERT_SCREEN_CENTERED, ALERT_MESSAGE_STRINGS, "A help server to display more help", "was not found. There will be a short", "delay while one is started.", " ", " ", NULL, ALERT_BUTTON_YES, "Continue", ALERT_BUTTON_NO, "Cancel", NULL) == ALERT_YES) { sprintf(command, "%s '%s' &", help_server_name, data); system(command); } } } return; } /* * Default request function */ static void help_request_default(client_window, client_data, client_event) Window client_window; caddr_t client_data; Event *client_event; { char *arg = help_get_arg(client_data), *text = (arg ? help_get_text() : NULL), buffer[HELPTEXTLINES][80], *array[HELPTEXTLINES+1]; Event event; int i, more_info = TRUE; int use_doc = (arg ? *arg != '\0' : FALSE); if (client_event) { event = *client_event; } if (text) { for (i = 0; text && i < HELPTEXTLINES; ++i, (text = help_get_text())) { array[i] = (char *)strncpy(buffer[i], text, sizeof(buffer[i]) - 1); if (buffer[i][strlen(buffer[i]) - 1] == '\n') buffer[i][strlen(buffer[i]) - 1] = '\0'; } array[i] = NULL; more_info = (alert_prompt(NULL, &event, HELP_DATA, "sunview:helpalert", ALERT_IMAGE, &help_request_icon, ALERT_POSITION, ALERT_SCREEN_CENTERED, ALERT_NO_BEEPING, TRUE, ALERT_MESSAGE_STRINGS_ARRAY_PTR, array, ALERT_BUTTON_YES, "Done", (use_doc ? ALERT_BUTTON_NO : 0), "More Help", 0) == ALERT_NO); } else if (text || (!text && !use_doc)) { help_request_failed(client_window, client_data, "No help is available", "sunview:helpnoinfo", &event); } /* This sends a help request directly to the help */ /* server, with no intervening Spot Help message. */ if (use_doc && more_info) { help_more(client_window, arg, &event); } } /* * Public interfaces */ void help_request(client, data, event) Window client; caddr_t data; Event *event; { if (help_request_func) { help_request_func(client, data, event); } } void help_more(client, data, event) Window client; char *data; Event *event; { if (! help_more_func) { help_more_func = help_more_default; } (*help_more_func)(client, data, event); } void help_set_request_func(func) void (*func)(); { help_request_func = func; } void help_set_more_func(func) void (*func)(); { help_more_func = func; } /* * callrpc(), with timeout parameter: */ static struct callrpc_private { CLIENT *client; int socket; int oldprognum, oldversnum, valid; char *oldhost; } *callrpc_private; callrpc2(host, prognum, versnum, procnum, inproc, in, outproc, out, tottimeout) char *host; xdrproc_t inproc, outproc; char *in, *out; struct timeval *tottimeout; { register struct callrpc_private *crp = callrpc_private; struct sockaddr_in server_addr; enum clnt_stat clnt_stat; struct hostent *hp; struct timeval timeout; if (crp == 0) { crp = (struct callrpc_private *)calloc(1, sizeof (*crp)); if (crp == 0) return (0); callrpc_private = crp; } if (crp->oldhost == NULL) { crp->oldhost = malloc(256); crp->oldhost[0] = 0; crp->socket = RPC_ANYSOCK; } if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum && strcmp(crp->oldhost, host) == 0) { /* reuse old client */ } else { crp->valid = 0; (void)close(crp->socket); crp->socket = RPC_ANYSOCK; if (crp->client) { clnt_destroy(crp->client); crp->client = NULL; } if ((hp = gethostbyname(host)) == NULL) return ((int) RPC_UNKNOWNHOST); timeout.tv_usec = 0; timeout.tv_sec = 5; bcopy(hp->h_addr, (char *)&server_addr.sin_addr, hp->h_length); server_addr.sin_family = AF_INET; server_addr.sin_port = 0; if ((crp->client = clntudp_create(&server_addr, (u_long)prognum, (u_long)versnum, timeout, &crp->socket)) == NULL) return ((int) rpc_createerr.cf_stat); crp->valid = 1; crp->oldprognum = prognum; crp->oldversnum = versnum; (void) strcpy(crp->oldhost, host); } clnt_stat = clnt_call(crp->client, procnum, inproc, in, outproc, out, *tottimeout); /* * if call failed, empty cache */ if (clnt_stat != RPC_SUCCESS) crp->valid = 0; return ((int) clnt_stat); }