archie/prospero/user/menu/menu.c
2024-05-27 16:13:40 +02:00

328 lines
7.3 KiB
C

/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* The menu API and client were written by Kwynn Buess (buess@isi.edu)
*/
#include <usc-copyr.h>
#include "menu.h"
#include "config.h"
#include <stdio.h>
#include <psite.h>
#include <perrno.h>
extern char *m_error;
static char error_buffer[300]; /* XXX Will have to replace this with the
flexible-length general Prospero string
handling routines. */
#define ck_fatal_err if ((m_error) != NULL) { fprintf(stderr,"%s",m_error); exit(1);}
VLINK set_environ(int argc,char *argv[]) {
int err;
VLINK vl,vl2,vl3,vl4;
VDIR_ST dir_st;
VDIR dir = &dir_st;
char *err_msg_1 = "\nNo initial directory is available\n\n";
if (argc == 0) {
vl = rd_vlink("/MENU");
if (vl != NULL) return vl;
#ifdef MENU_DEFAULT_HOST
#ifdef MENU_DEFAULT_DIRECTORY
vl = vlalloc();
vl->hsoname = stcopy(MENU_DEFAULT_DIRECTORY);
vl->host = stcopy(MENU_DEFAULT_HOST);
return vl;
#endif
#endif
#ifndef P_SITE_DIRECTORY
fprintf(stderr,"%s",err_msg_1);
return NULL;
#endif
#ifndef P_SITE_HOST
fprintf(stderr,"%s",err_msg_1);
return NULL;
#endif
vl = vlalloc();
vl->hsoname = stcopy(P_SITE_DIRECTORY);
vl->host = stcopy(P_SITE_HOST);
vdir_init(dir);
if (p_get_dir(vl,P_SITE_MASTER_VSLIST,dir,GVD_FIND,NULL)
!= PSUCCESS)
{
fprintf(stderr,"%s",err_msg_1);
return NULL;
}
vllfree(vl);
vl2 = dir->links;
if (vl2 == NULL) return NULL;
if (p_get_dir(vl2,P_PROTOTYPE_VS,dir,GVD_FIND,NULL)
!= PSUCCESS)
{
fprintf(stderr,"%s",err_msg_1);
return NULL;
}
/* vllfree(vl2); */
vl3 = dir->links;
if (vl3 == NULL) return NULL;
if (p_get_dir(vl3,"ROOT",dir,GVD_FIND,NULL) != PSUCCESS) {
fprintf(stderr,"%s",err_msg_1);
return NULL;
}
/* vllfree(vl3); */
vl4 = dir->links;
if (vl4 == NULL) return NULL;
if (p_get_dir(vl4,"MENU",dir,GVD_FIND,NULL) != PSUCCESS) {
fprintf(stderr,"%s",err_msg_1);
return NULL;
}
/* vllfree(vl4); */
if (dir->links != NULL) return (dir->links);
return NULL;
}
else if (argc == 1) {
vl = rd_vlink(argv[0]);
if (vl == NULL) {
m_error = error_buffer;
sperrmesg(error_buffer,"ERROR: ", 0 ,NULL);
return NULL;
}
return vl;
}
else if (argc == 3) {
argc--;argv++;
vl = vlalloc();
vl -> host = stcopy(argv[0]);
vl -> hsoname = stcopy(argv[1]);
return vl;
}
return NULL;
}
void init_menu(MCS *mc,VLINK first_link) {
VLINK temp;
MCS mcs = (MCS) stalloc(sizeof(struct menu_control_struct));;
if (mcs == NULL) {
fprintf(stderr,"\nOUT OF MEMORY!!!\n\n");
exit(1);
}
temp = first_link;
if (temp == NULL) {
fprintf(stderr,"\nNo initial menu could be found\n\n");
exit(1);
}
mcs->warning = NULL;
*p_warn_string = '\0';
mcs->current = m_get_menu(temp);
if (*p_warn_string)
mcs->warning = tkappend(p_warn_string, mcs->warning);
p_warn_string[0] = '\0';
ck_fatal_err;
mcs->earlier = mcs->later = NULL;
mcs->name_of_parent = stcopy(m_item_description(temp));
ck_fatal_err;
vlfree(temp);
(*mc) = mcs;
}
void get_menu(MCS *mcs,VLINK parent) {
MCS new = (MCS) stalloc(sizeof(struct menu_control_struct));
if (new == NULL) {
fprintf(stderr,"\nOUT OF MEMORY!!!\n\n");
exit(1);
}
(*mcs)->later = new;
new->earlier = (*mcs);
new->name_of_parent = stcopy(m_item_description(parent));
new->later = NULL;
new->warning = NULL;
*p_warn_string = '\0';
new->current = m_get_menu(parent);
if (*p_warn_string)
new->warning = tkappend(p_warn_string, new->warning);
p_warn_string[0] = '\0';
(*mcs) = new;
if (m_error != NULL) {
fprintf(stderr,"%s\n",m_error);
printf("\n\nRepeating previous menu\n");
m_error = NULL; /* clear error flag */
up_menu(mcs);
}
}
void get_search(MCS *mcs,VLINK parent)
{
MCS new = (MCS) stalloc(sizeof(struct menu_control_struct));
if (new == NULL) {
fprintf(stderr,"\nOUT OF MEMORY!!!\n\n");
exit(1);
}
(*mcs)->later = new;
new->warning = NULL;
new->earlier = (*mcs);
new->name_of_parent = stcopy(m_item_description(parent));
new->later = NULL;
new->warning = NULL;
*p_warn_string = '\0';
new->current = open_search(parent);
if (*p_warn_string)
new->warning = tkappend(p_warn_string, (new)->warning);
(*mcs) = new;
p_warn_string[0] = '\0';
if (m_error != NULL) {
fprintf(stderr,"%s\n",m_error);
printf("\n\nRepeating previous menu\n");
m_error = NULL; /* clear error flag */
up_menu(mcs);
}
}
/* Read value from user and return */
int query_choice(MCS *mcs) {
printf("\nPress a number to select a menu item, q to Quit");
if (!top_menu(mcs)) printf(", u to go up a menu");
printf(": ");
return get_top_level_answer();
/*
if (answer[0] == 'q') return -1;
if (answer[0] == 'u') return 0 ;
*/
/*
for (cnt=0;
(isdigit(answer[cnt]))
&& (answer[cnt] != '\0')
&& (answer[cnt]!= '\n')
;
cnt++);
if (answer[cnt] == '\n') answer[cnt] = '\0';
temp = atoi(answer);
if (temp == 0) return -2;
*/
/* If the answer string got to the end that means that all components were
digits and it's a valid number (values that are too high are handled
in return_choice().
*/
/* if (answer[cnt] == '\0') return atoi(answer); */
/* If it ended because there were no digits, then it's invalid. */
/* else return -2; */
}
int top_menu(MCS *mcs) {
if ((*mcs)->earlier == NULL) return 1;
else return 0;
}
void up_menu(MCS *mcs) {
if ((*mcs)->current != NULL) {
vllfree((*mcs)->current);
}
stfree((*mcs)->name_of_parent);
(*mcs) = (*mcs)->earlier;
stfree((*mcs)->later);
(*mcs)->later = NULL;
}
void print_current_menu(MCS *mcs) {
int cnt = 0;
VLINK trans = (*mcs)->current;
char *temp;
int temp_cl;
printf("\n\nMenu for %s\n",(*mcs)->name_of_parent);
if ((*mcs)->warning) {
TOKEN tk;
puts("Got the following warning(s) from Prospero:");
for (tk = (*mcs)->warning; tk; tk = tk->next)
puts(tk->token);
tkfree((*mcs)->warning); (*mcs)->warning = NULL;
}
putchar('\n');
while (trans != NULL) {
temp = m_item_description(trans);
if (!(temp == NULL || trans->linktype == 'I')) {
printf("%4d",++cnt);
if ((temp_cl = m_class(trans)) == M_CLASS_MENU) printf("> ");
else if (temp_cl == M_CLASS_PORTAL) printf("] ");
else if (temp_cl == M_CLASS_SEARCH) printf(": ");
else printf(". ");
printf("%s\n",temp);
}
trans = trans -> next;
}
}
/* Walks linked list of VLINKS and returns link 'ch' (first is 1) */
VLINK return_choice(int ch,MCS *mcs) {
int cnt = 0;
VLINK temp = (*mcs)->current;
do {
if (!(get_item_desc(temp) == NULL || temp->linktype == 'I')) cnt++;
if (cnt != ch) temp = temp -> next;
} while (cnt != ch && temp != NULL);
return temp;
}
int is_empty(MCS *to_check) {
if ((*to_check)->current == NULL) return 1;
else return 0;
}
/* These are not yet implemented; they will soon replace the current
calls to stalloc(). */
#if 0
MCS
mcsalloc(void)
{
}
void
mcsfree(MCS mcs)
{
}
#endif