/*-------------------------------------------------------------------+ | Copyright (c) 1996, SAS Institute Inc. | | Unpublished - All Rights Reserved | | S A S / C S A M P L E | | | | NAME: CMSMENU | | LANGUAGE: C | | PURPOSE: Demonstrate use of the SAS/C FSSL to develop menus, | | submenus, help screens, and error displays | | SYSTEM NOTES: Written for CMS only. The only thing that is | | operating system dependent is the CMS commands. | | INPUT: via SAS/C FSSL | | OUTPUT: via SAS/C FSSL | | | | CMS - | | COMPILE: GLOBAL MACLIB LC370 L$FSSL | | LC370 CMSMENU | | LINK: GLOBAL TXTLIB LC370BAS LC370STD L$FSSL | | CLINK CMSMENU (GENMOD | | EXECUTE: CMSMENU | | | | MISC NOTES: SAS/C FSSL *must* be installed. | | See OSMENU for an OS version of this program. | | | +-------------------------------------------------------------------*/ #include #include #include #include #define COMMAND 100 time_t timeval; int field = 1000; struct FS_READPAN input; struct FS_READSCR screen; struct FS_TERMATTR *scr_attr; char command[131], errmsg[132], tm[26]; char *menu = "MENU1", *submenu = "MENU2", *error = "ERROR"; char *header = "Simplified CMS Action Menu"; char msg[6][51]; char *menuline[] = { /* max length displayed is 40 */ " 0 - Display help on this menu ", " 1 - Request general CMS help ", " 2 - List all datasets on the Adisk ", " 3 - List all minidisks attached ", " 4 - Display all libraries globalled ", " 5 - Display 'all' information ", " 6 - Display files currently FILEDEFed ", " 7 - Display all jobs in virtual reader ", " 8 - Log onto another system ", " 9 - Enter any CMS command " }; char *menucmd[] = { /* corresponding command */ "n/a", "cms: help", "cms: filel", "cms: q disk", "cms: q library", "cms: q all", "cms: file", "cms: rdrlist", "n/a", "n/a" }; /*-------------------------------------------------------------------+ | The main is used to start the full screen environment, define each | | of the different panels which will be displayed, and then display | | the main panel waiting for input. Upon input it will decide what | | was requested and respond accordingly. | +-------------------------------------------------------------------*/ main() { /*----------------------------------------------------------------+ | define the main menu and sub-menu panels | +----------------------------------------------------------------*/ fsinit(errmsg); scr_attr = fsrttm(); define_main(); define_sub(); define_error(); /*----------------------------------------------------------------+ | Display main menu panel, wait for input and then decide which | | command was requested. | +----------------------------------------------------------------*/ for (;;) { /* update the panel to reflect any changes */ time(&timeval); strcpy(tm, ctime(&timeval)); memset(command, 0, sizeof(command)); fsdspn(menu, 0, 1, 1, COMMAND, 1, FS_FORCE); /* wait for input from the user */ screen = fsrdsc(); if ((screen.aid == PF_3) || (screen.aid == PF_15)) { fsterm(); exit(EXIT_SUCCESS); } /* read the panel...update input from user */ input = fsrdpn(menu); /* decide what user asked for... */ if (*command == '0') /* menu help */ noop(0); else if (*command == '1') /* general help */ system(menucmd[1]); else if (*command == '2') /* list user datasets */ system(menucmd[2]); else if (*command == '3') /* list allocated dsn */ system(menucmd[3]); else if (*command == '4') /* display user profile */ system(menucmd[4]); else if (*command == '5') /* receive messages */ system(menucmd[5]); else if (*command == '6') /* list broadcast msgs */ system(menucmd[6]); else if (*command == '7') /* display job status */ system(menucmd[7]); else if (*command == '8') /* log onto system */ noop(1); else if (*command == '9') /* submenu selection */ { memset(command, '\0', 130); /* display new menu and wait for user response */ fsdspn(submenu, 0, 1, 1, 0, 0, FS_FORCE); screen = fsrdsc(); if (screen.aid == ENTER_KEY) { input = fsrdpn(submenu); memcpy(command, "CMS:", 4); /* make it one command */ strcat(command, command+5); strcat(command, command+46); strcat(command, command+86); system(command); } else input = fsrdpn(submenu); /* clear input pending */ } } return(0); } /*-------------------------------------------------------------------+ | This routine will decide which display to generate and then store | | the message into the error/message display panel fields | +-------------------------------------------------------------------*/ noop(code) int code; { int i; /*----------------------------------------------------------------+ | clear message display area and then set error (or message) | | display. | +----------------------------------------------------------------*/ for (i=0; i<6; i++) memset(msg[i], ' ', 50); if (code == 1) { strcpy(msg[0], "----------------> W A R N I N G <-----------------"); strcpy(msg[1], "It has been determined that you are not authorized"); strcpy(msg[2], "for the action requested. Information concerning "); strcpy(msg[3], "your userid, name, location, and phone have been "); strcpy(msg[4], "entered into an access violation database. "); strcpy(msg[5], "----------------> W A R N I N G <-----------------"); } /*----------------------------------------------------------------+ | display message and wait for user to read and press PF/enter key| +----------------------------------------------------------------*/ fsdspn(error, 0, 1, 1, 0, 0, FS_FORCE | FS_IGNINPUT); screen = fsrdsc(); input = fsrdpn(error); return(0); } /*-------------------------------------------------------------------+ |+------------------------------------------------------------------+| ||NOTE: The following routines are used only to define the display || || panels. They could be dynamically loaded at the beginning || || of the program and then unloaded since they are needed only|| || at that time. This would then free up this memory. || |+------------------------------------------------------------------+| +-------------------------------------------------------------------*/ /*-------------------------------------------------------------------+ | This routine is used to define the main menu screen. | +-------------------------------------------------------------------*/ define_main() { int i, len, row, col, color; static char userid[L_cuserid+1], sname[11], ename[11]; static int battr, sattr, sattr2, mattr, battr2, tattr; static char *mtitle, *tb1, *tb2; /*----------------------------------------------------------------+ | define panel and size | +----------------------------------------------------------------*/ fsdfpn(menu, scr_attr->prim_row, scr_attr->prim_col); /*----------------------------------------------------------------+ | define fields for the border | +----------------------------------------------------------------*/ battr = PROTECTED | REVERSE_VIDEO | BRIGHT; color = RED; len = (scr_attr->prim_col - 2) + 1; tb1 = malloc(len + 3); border(menu, tb1, 1, scr_attr->prim_row, 2, scr_attr->prim_col, battr, color, len, " ", " ", " "); len -= 4; /*----------------------------------------------------------------+ | define field for title | +----------------------------------------------------------------*/ tattr = PROTECTED | BRIGHT; color = MAGENTA; mtitle = malloc(len + 3); title(menu, header, mtitle, 2, 4, tattr, color, len); /*----------------------------------------------------------------+ | define selection line fields | +----------------------------------------------------------------*/ row = 3; col = 4; sattr = PROTECTED; color = BLUE; fsdffd(menu, field++, row, col, 12, "SELECTION==>", &sattr, color, BLANK); col += 13; sattr2= BRIGHT | AUTOREAD; color = WHITE; fsdffd(menu, COMMAND, row, col, 2, command, &sattr2, color, BLANK); /*----------------------------------------------------------------+ | define fields on menu | +----------------------------------------------------------------*/ row += 3; col = 20; mattr = PROTECTED; color = YELLOW; for (i=0; i<=9; i++) { fsdffd(menu, field++, row, col, 40, menuline[i], &mattr, color, BLANK); row += 1; } /*----------------------------------------------------------------+ | define fields for misc information (at bottom of screen) | +----------------------------------------------------------------*/ row = scr_attr->prim_row - 3; col = 4; battr2= PROTECTED; color = GREEN; len = (scr_attr->prim_col - (col * 2)) + 3; tb2 = malloc(len + 3); border(menu, tb2, row, (scr_attr->prim_row-1), col, (scr_attr->prim_col-2), battr2, color, len, "+", "-", "|"); row++; strcpy(sname, sysname()); fsdffd(menu, field++, row, 6, 10, sname, &battr2, color, BLANK); strcpy(ename, envname()); fsdffd(menu, field++, row, 20, 10, ename, &battr2, color, BLANK); cuserid(userid); fsdffd(menu, field++, row, 35, L_cuserid, userid, &battr2, color, BLANK); time(&timeval); strcpy(tm, ctime(&timeval)); fsdffd(menu, field++, row, 40+L_cuserid, 24, tm, &battr2, color, BLANK); return(0); } /*-------------------------------------------------------------------+ | This routine creates the CMS command entry screen | +-------------------------------------------------------------------*/ define_sub() { int color, len; static int tsoattr, cmdattr, tattr; static char *stitle; /*----------------------------------------------------------------+ | define panel and size | +----------------------------------------------------------------*/ fsdfpn(submenu, scr_attr->prim_row, scr_attr->prim_col); /*----------------------------------------------------------------+ | define field for title of submenu | +----------------------------------------------------------------*/ len = scr_attr->prim_col - 1; tattr = PROTECTED | BRIGHT; color = GREEN; stitle = malloc(len + 4); title(submenu, "CMS Command Entry Screen", stitle, 1, 2, tattr, color, len); /*----------------------------------------------------------------+ | define field for CMS input | +----------------------------------------------------------------*/ tsoattr = BRIGHT | PROTECTED; color = MAGENTA; fsdffd(submenu, field++, 8, 2, 20, "Enter CMS Command==>", &tsoattr, color, BLANK); cmdattr = BRIGHT | AUTOREAD | REVERSE_VIDEO; color = YELLOW; fsdffd(submenu, field++, 8, 25, 40, command+5, &cmdattr, color, NULL); fsdffd(submenu, field++, 9, 25, 40, command+46, &cmdattr, color, NULL); fsdffd(submenu, field++, 10, 25, 40, command+86, &cmdattr, color, NULL); return(0); } /*-------------------------------------------------------------------+ | This routine defines the error/message display panel | +-------------------------------------------------------------------*/ define_error() { int len, color; static int errbattr, errmattr, rattr; static char *etb1; /*----------------------------------------------------------------+ | define panel and size | +----------------------------------------------------------------*/ fsdfpn(error, scr_attr->prim_row, scr_attr->prim_col); /*----------------------------------------------------------------+ | define fields for the border | +----------------------------------------------------------------*/ errbattr = PROTECTED | REVERSE_VIDEO | BRIGHT; color = RED; len = (scr_attr->prim_col - 2) + 1; etb1 = malloc(len + 3); border(error, etb1, 1, scr_attr->prim_row, 2, scr_attr->prim_col, errbattr, color, len, " ", " ", " "); /*----------------------------------------------------------------+ | define fields for message display | +----------------------------------------------------------------*/ errmattr = PROTECTED | BRIGHT; color = WHITE; fsdffd(error, field++, 10, 15, 50, msg[0], &errmattr, color, BLANK); fsdffd(error, field++, 11, 15, 50, msg[1], &errmattr, color, BLANK); fsdffd(error, field++, 12, 15, 50, msg[2], &errmattr, color, BLANK); fsdffd(error, field++, 13, 15, 50, msg[3], &errmattr, color, BLANK); fsdffd(error, field++, 14, 15, 50, msg[4], &errmattr, color, BLANK); fsdffd(error, field++, 15, 15, 50, msg[5], &errmattr, color, BLANK); /*----------------------------------------------------------------+ | tell user how to get rid of current display | +----------------------------------------------------------------*/ rattr = PROTECTED | BRIGHT; color = BLUE; fsdffd(error, field++, scr_attr->prim_row-3, 14, 52, "Press any PF key or enter to return to the main menu", &rattr, color, BLANK); return(0); } /*-------------------------------------------------------------------+ | This routine is used to define all the fields needed to create the | | look of a border. | +-------------------------------------------------------------------*/ border(panel, tb, r1, r2, c1, c2, attr, color, len, cor, hor, ver) char *panel, *tb; int r1, r2, c1, c2, attr, color, len; char *cor, *hor, *ver; { int row; /*----------------------------------------------------------------+ | define fields to create the border | +----------------------------------------------------------------*/ memset(tb, '\0', (len+2)); memset(tb, *hor, len); /* create the horizontal field */ *tb = *cor; *(tb+len-1) = *cor; /* define field on top - only one needed */ fsdffd(panel, field++, r1, c1, len, tb, &attr, color, BLANK); /* define field on bottom - only one needed */ fsdffd(panel, field++, r2, c1, len, tb, &attr, color, BLANK); /* define fields on left/right - one field needed for each row */ /* and each side. */ for (row=r1+1; row