home *** CD-ROM | disk | FTP | other *** search
- /* menudrv.c */
-
- /*-------------------------------------------------------------------+
- | Program: menudrv (PC menu driver) |
- | Programmer: John Queern, CIS 250-1, Belleville Area College |
- | Purpose: To provide a simple, user-adjustable menu system |
- | for an IBM PC-compatible which will allow you to |
- | select programs or groups of programs by simply |
- | pressing a key from the menu. |
- | |
- | Date written: Jan-Mar '89 (C version) |
- | Last changed: 3/30/89 |
- | Notes: placed in the public domain |
- | to compile, use Turbo C, and menudrv.prj proj file |
- | |
- +-------------------------------------------------------------------*/
-
- /* Important!: use a memory model which employs far data pointers, so that
- the video memory may be accessed directly using library functions;
- possible choices: compact, large, or huge (I recommend compact) */
-
- /* This version does not include the alarm/reminder facility; it has
- been kept as short and simple as possible for classroom/diskette use;
- Note: to make the executable even shorter, comment out the definition
- of "editable" in menudrv.h. This will produce a menu which will not
- permit the user to edit menu items. Very useful for the classroom! */
-
- #include "menudrv.h"
- #include <alloc.h>
- #include <conio.h>
- #include <ctype.h>
- #include <dos.h>
- #include <bios.h>
- #include <process.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- /*========================================================================*/
- /* declarations */
-
- char mname[13][12] = { "December",
- "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December"
- };
- char wdname[8][12] = {"Sunday",
- "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
- "Saturday", "Sunday"
- };
- int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
- string80 blank =
- " ";
- menuptr item[maxitem];
- char edscreen[22][82];
- int items;
- char inpline[132], otline[132];
- string80 temp, temp2, resp;
- int lines;
- FILE *datafile;
- FILE *batfile;
- FILE *parmfile;
- int month, day, year, weekday, hour, min, sec, lastsec, lastmin, hun;
- char cmenu;
- char citem;
- string40 cdescription;
- char ctomenu;
- int done, good, initialized, gotchild, datachanged, parmchanged;
- int x,y,i,j,k,n,p,t,r;
- int col;
- char *cptr;
- unsigned char b;
- char ch, c2, firstpass;
- unsigned char retcd;
- lineptr cp, np, op;
- menuitem tempitem;
- int bfore, bback;
- char holiday[13][32];
- char specialday[13][32];
- int insert=0;
-
- string14 fore1, back1; /*date/time, message colors*/
- string14 fore2, back2; /*calendar, alarm box colors*/
- string14 fore3, back3; /*selection item colors*/
- string14 fore4, back4; /*colors for alarm items*/
- string14 fore5, back5; /*colors for ed screen*/
- string14 fore6, back6; /*colors for ed help screen*/
-
- vptr sbuff[5]; /*screen buffers*/
- char monochrome; /*mono flag*/
-
- /*========================================================================*/
-
- char *strdel(char st[],int start,int count)
- /* delete <count> chars from string <st> starting at <start> */
- {
- int i,l;
-
- l = strlen(st);
- for (i=start;i<l;i++) st[i] = st[i+count];
-
- }
-
- int nonblank (char *st)
- /* check a string to see if it contains anything except blanks; return
- 1 (=TRUE) if the string contains something nonblank; 0 (=FALSE) otherwise */
- {
- int flag;
- flag = FALSE; /* assume everything is blank */
- while ((*st!=0) && (flag==FALSE)) {
- flag=((*st!=' ') && (*st!=0));
- st++;
- }
- return flag;
- }
-
- /*========================================================================*/
- /* call "stub" for missing functions -- a programmer's convenience */
-
- void stub(void)
- {
- sound(400);
- delay(250);
- sound(200);
- delay(250);
- nosound();
- }
-
- /*========================================================================*/
-
- void init(int argv, char *argc[])
- {
- int i,j;
- FILE *datfile;
-
- if (argv>1) cmenu=toupper(*argc[1]);
- else cmenu='M'; /* first menu */
- done=FALSE;
-
- /* establish default colors (getdata will replace if parms found) */
- strcpy(fore1,"yellow"); /*date/time, message colors*/
- strcpy(back1,"black");
- strcpy(fore2,"cyan"); /*calendar, alarm box colors*/
- strcpy(back2,"black");
- strcpy(fore3,"green"); /*selection item colors*/
- strcpy(back3,"black");
- strcpy(fore4,"cyan"); /*colors for alarm items*/
- strcpy(back4,"black");
- strcpy(fore5,"white"); /*colors for ed screen*/
- strcpy(back5,"red");
- strcpy(fore6,"white"); /*colors for ed help screen*/
- strcpy(back6,"blue");
-
- for (i=1;i<5;i++) sbuff[i]=calloc(1,sizeof(*(sbuff[i])));
- getsysdate();
- getdata();
- firstpass=TRUE;
- lastmin=0;
- for (i=1;i<13;i++)
- for (j=1;j<32;j++) {
- holiday[i][j]=FALSE;
- specialday[i][j]=FALSE;
- }
- /* set up holidays based on data files */
- datfile = fopen("year.hol","r");
- if (datfile!=NULL) {
- while (fscanf(datfile,"%d %d",i,j)>0)
- if ((i>0) && (i<13) && (j>0) && (j<31)) holiday[i][j]=TRUE;
- fclose(datfile);
- }
- datfile=fopen("year.spc","r");
- if (datfile!=NULL) {
- while(fscanf(datfile,"%d %d",i,j)>0)
- if ((i>0) && (i<13) && (j>0) &&(j<31)) specialday[i][j]=TRUE;
- }
-
- datachanged = FALSE;
- parmchanged = FALSE;
-
- }
-
- /*========================================================================*/
-
- void display_menu()
- {
-
- /*create the menu screen*/
- border(color(back1));
- bfore = color(fore1);
- bback = color(back1);
- bclear(1);
-
- /*clear screen buffer 1*/
- bcalendar(50,3);
- getsystime();
- dispdate();
- bwrite(1,1,24," Press the key corresponding to your desired function. Press End to exit.");
-
- #ifdef editable
- bwrite(1,1,25," F1=add/edit item F2=del item F3=move item F4=edit colors ");
- #else
- bwrite(1,1,25," F4=edit colors ");
- #endif
-
- bfore = color(fore3);
- bback = color(back3);
- bwrite(1,1,3,"The following selections are available:");
- y = 5;
- i = 1;
- while ( (i < items) && (item[i]->id != cmenu) ) i++;
- if ( item[i]->id != cmenu ) {
- cprintf("%s%c%c\n", "Cannot find information for menu ", cmenu, '.');
- cprintf("%c", '\x07');
- if ( cmenu == 'M' ) {
- cprintf("%s", "Press any key to continue...");
- ch=getch();
- clrscr();
- exit(1);
- }
- else {
- cmenu = 'M';
- }
- }
- else { /*got initial value*/
- j = i; /*i=first entry for this menu*/
- while ( (item[j]->id == cmenu) && (j <= items) ) {
- sprintf(temp,"%c %-40s",item[j]->prompt,item[j]->description);
- bwrite(1,1,y,temp);
- y++;
- j++;
- }
- good = FALSE;
- bfore = color(fore1);
- bback = color(back1);
- bwrite(1,1,22,"Selection? ");
- restorescreen(1);
- }
- }
-
- /*========================================================================*/
-
- void main(int argv,char *argc[])
- {
- init(argv,argc);
- binit();
- do {
- display_menu();
- if ( item[i]->id == cmenu ) {
- while ( ! good ) {
- L10:
- if ( color(back1) > 7 ) textcolor(color(fore1) + blink);
- else textcolor(color(fore1));
- textbackground(color(back1));
- gotoxy(12,22);
- lastsec = sec;
- while ( ! (bioskey(1))) { /* while not keypressed */
- getsystime();
- if ( sec != lastsec ) {
- gotoxy(60,1);
- disptime();
- gotoxy(12,22);
- lastsec = sec;
- }
- }
- firstpass = FALSE;
- if ( color(back3) > 7 ) textcolor(color(fore3) + blink);
- else textcolor(color(fore3));
- textbackground(color(back3));
- ch=getch();
- if ( ch == 0 ) { /*handle End and Function keys*/
- c2=getch();
- switch ( c2 ) {
- case '\x4F': /*End*/
- {
- batfile = fopen(bfname,"w");
- fclose(batfile);
- clrscr();
- done = TRUE;
- goto L90;
- }
- #ifdef editable
- case '\x3B': /*F1-add or edit item*/
- {
- gotoxy(1,22);
- clreol();
- cprintf("%s", "Add/edit what item code? ");
- citem=getch();
- if ( citem < '\x21' ) {
- cprintf("%c", '\x07');
- restorescreen(1);
- goto L10;
- }
- citem = toupper(citem);
- cprintf("%c", citem);
- j = i;
- /*look for match*/
- while ( (item[j]->prompt != citem)
- && (j < items) && (item[j]->id == cmenu) ) j++;
- if ( (item[j]->prompt != citem)
- || (item[j]->id != cmenu) ) {
- /*this is a new item*/
- for ( n = 1; n <= 19; n++ ) {
- /* blank the buffer lines */
- edscreen[n][0]=0;
- pad(edscreen[n],77);
- }
- cdescription[0] = 0;
- gotoxy(1,22);
- clreol();
- cprintf("%s", "Which item should this one follow? ");
- ch=getch();
- ch = toupper(ch);
- if ( ch == '\x0D' ) {
- /*top of menu*/
- j = 1;
- while ( (item[j]->id != cmenu) ) j++;
- }
- else {
- j = i;
- /*look for match*/
- while ( (item[j]->prompt != ch) &&
- (j < items) && (item[j]->id == cmenu) ) j++;
- if ( item[j]->prompt != ch ) {
- cprintf("%c", '\x07');
- restorescreen(1);
- goto L10;
- }
- j++; /*position for new item*/
- }
- item[items + 1] = (menuptr) calloc(1,sizeof(*item[items + 1]));
- for ( n = items + 1; n >= j + 1; --n ) {
- *item[n] = *item[n - 1];
- }
- items++;
- {
- item[j]->id = cmenu;
- item[j]->prompt = citem;
- item[j]->description[0] = 0;
- item[j]->tomenu = '*';
- item[j]->firstline = NULL;
- }
- do {
- gotoxy(1,22);
- clreol();
- cprintf("%s", "Is this item another menu? ");
- ch=getch();
- ch = toupper(ch);
- if ( ! ((ch=='Y') || (ch=='N')) ) putch(7);
- } while ( ! ((ch=='Y') || (ch=='N')) );
- if ( ch == 'Y' ) {
- /*adding a submenu reference*/
- cdescription[0] = 0;
- ctomenu = ' ';
- editmenu();
- ctomenu = toupper(ctomenu);
- citem = toupper(citem);
- {
- item[j]->id = cmenu;
- item[j]->prompt = citem;
- strcpy(item[j]->description,cdescription);
- item[j]->tomenu = ctomenu;
- item[j]->firstline = NULL;
- }
- /*check to see if target menu exists*/
- n = 1;
- while ( (item[n]->id != ctomenu)
- && (n < items) ) n++;
- if ( item[n]->id != ctomenu ) {
- /*add one item for the new menu*/
- item[items + 1] =
- (menuptr) calloc(1,sizeof(*item[items + 1]));
- items++;
- {
- item[items]->id = ctomenu;
- item[items]->tomenu = 'M';
- item[items]->prompt = 'X';
- strcpy(item[items]->description,
- "Return to Main Menu");
- item[items]->firstline = NULL;
- }
- }
- datachanged = TRUE;
- goto L90;
- } /*if new menu entry*/
- }
- else { /*old item*/
- if ( item[j]->tomenu != '*' ) {
- strcpy(cdescription,item[j]->description);
- ctomenu = item[j]->tomenu;
- editmenu(); /* ** */
- strcpy(item[j]->description,cdescription);
- item[j]->tomenu = ctomenu;
- item[j]->prompt = citem;
- datachanged = TRUE;
- goto L90;
- }
- /*load the item's data*/
- for ( n = 1; n <= 19; n++ ) {
- edscreen[n][0]=0;
- pad(edscreen[n],77);
- }
- cp = item[j]->firstline;
- i = 1;
- while ( (cp != NULL) && (i <= 19) ) {
- strcpy(edscreen[i],cp->line);
- pad(edscreen[i],77);
- cp = cp->next;
- i++;
- }
- strcpy(cdescription,item[j]->description);
- }
- edit();
- /*save results*/
- strcpy(item[j]->description,cdescription);
- cp = item[j]->firstline;
- i = 1;
- op = NULL; /* op holds last valid pointer */
- while ( (cp != NULL) && (i <= 19) ) {
- strcpy(cp->line,edscreen[i]);
- op = cp;
- cp = cp->next;
- i++;
- }
- cp = op; /*restore last pointer*/
- /*catch any added lines*/
- for ( n = i; n <= 19; n++ ) {
- if ( nonblank(edscreen[n]) ) {
- np = (lineptr) calloc(1,sizeof(*np));
- strcpy(np->line,edscreen[n]);
- if ( item[j]->firstline == NULL ) {
- item[j]->firstline = np;
- }
- else {
- cp->next = np;
- }
- np->next = NULL;
- cp = np;
- }
- }
- datachanged = TRUE;
- goto L90;
- }
- case '\x3C': /*F2-delete item*/
- {
- gotoxy(1,22);
- clreol();
- cprintf("%s", "Delete which item? ");
- citem=getch();
- cprintf("%c", citem);
- citem = toupper(citem);
- j = i;
- /*look for match*/
- while ( (item[j]->prompt != citem) && (j < items)
- && (item[j]->id == cmenu) ) j++;
- if ( item[j]->prompt != citem ) {
- cprintf("%c", '\x07');
- restorescreen(1);
- goto L10;
- }
- gotoxy(1,22);
- clreol();
- cprintf("%s%s%s", "Delete ",
- item[j]->description, " (Y/N)? ");
- ch=getch();
- ch = toupper(ch);
- if ( ch == 'Y' ) {
- /* free storage for deleted item's lines */
- cp = item[j]->firstline;
- while (cp != NULL) {
- op=cp->next;
- free(cp);
- cp=op;
- }
- /* shift everything down 1 */
- for ( n = j; n < items; n++) {
- *item[n] = *item[n + 1];
- }
- /* free storage for previous last item */
- free(item[items]);
- item[items]=NULL;
- items--;
- datachanged = TRUE;
- }
- goto L90;
- }
- case '\x3D': /*F3 - move item*/
- {
- gotoxy(1,22);
- clreol();
- cprintf("%s", "Move which item? ");
- citem=getch();
- cprintf("%c", citem);
- citem = toupper(citem);
- j = i;
- /*look for match*/
- while ( (item[j]->prompt != citem) && (j < items)
- && (item[j]->id == cmenu) ) {
- j = j + 1;
- }
- if ( item[j]->prompt != citem ) {
- /*item not found*/
- gotoxy(1,22);
- cprintf("%s%s", "Item not found. ",
- "Press a key to continue.");
- ch=getch();
- restorescreen(1);
- goto L10;
- }
- gotoxy(1,22);
- clreol();
- cprintf("%s",
- "Which item should this one follow? ");
- ch=getch();
- ch = toupper(ch);
- if ( ch == '\x0D' ) {
- /*top of menu*/
- n = 1;
- while ( (item[n]->id != cmenu) ) n++;
- }
- else {
- n = i;
- /*look for match*/
- while ( (item[n]->prompt != ch) && (n < items)
- && (item[n]->id == cmenu) ) n++;
- if ( item[n]->prompt != ch ) {
- cprintf("%c", '\x07');
- restorescreen(1);
- goto L10;
- }
- n++; /*position for new item*/
- }
- /*item being moved is item[j]; we are */
- /* moving it to position [n]*/
- tempitem = *item[j]; /*save item*/
- if ( n < j ) {
- for ( k = j; k >= n + 1; --k ) {
- *item[k] = *item[k - 1];
- }
- *item[n] = tempitem;
- }
- else {
- if ( j < n ) {
- n--;
- for ( k = j; k <= n - 1; ++k ) {
- *item[k] = *item[k + 1];
- }
- *item[n] = tempitem;
- }
- }
- goto L90;
- }
- #endif
- case '\x3E': /*F4-edit colors*/
- {
- editcolor(); /* ** */
- parmchanged = TRUE;
- goto L90;
- }
- default:
- goto L10;
- } /*case*/
- } /*if #0*/
- cprintf("%c", ch);
- ch = toupper(ch);
- j = i; /*look for match*/
- while ( (item[j]->prompt != ch) && (j < items)
- && (item[j]->id == cmenu) ) j++;
- if ( (item[j]->prompt != ch) || (item[j]->id != cmenu) ) {
- cprintf("%c", '\x07');
- }
- else {
- good = TRUE;
- }
- } /*while not good*/
-
- /*user has selected item[j]*/
- if ( item[j]->tomenu != '*' ) cmenu = item[j]->tomenu;
- else { /*doing action for the '*' item*/
- cp = item[j]->firstline;
- /*determine whether background job requested or not*/
- if ( cp->line[0] == '&' ) gotchild = TRUE;
- else gotchild = FALSE;
- if ( ! gotchild ) batfile = fopen(bfname,"w");
- while ( cp != NULL ) {
- if ( strstr(cp->line,"[") == NULL ) {
- if ( gotchild ) strcpy(temp2,cp->line);
- else fprintf(batfile,"%s\n", cp->line);
- }
- else { /*handle [xx] parameter passing*/
- strcpy(temp, cp->line);
- otline[0] = 0;
- do {
- cptr = strstr(temp,"[");
- if ( cptr == NULL ) strcat(otline,temp);
- else {
- *cptr=0;
- strcat(otline,temp);
- *cptr=' ';
- strdel(temp,0,cptr-temp+1);
- gotoxy(1,22);
- clreol();
- cptr = strstr(temp,"]");
- *cptr=0;
- cprintf("%s%c", temp, ' ');
- *cptr=' ';
- resp[0]=0;
- col=1;
- getstring(wherex(),wherey(),&col,resp,78-wherex());
- trim(resp);
- strcat(otline,resp);
- strdel(temp,0,cptr-temp+1);
- cptr = strstr(temp,"[");
- } /*else*/
- } while ( cptr != NULL );
- if ( gotchild ) strcpy(temp2,otline);
- else fprintf(batfile,"%s\n",otline);
-
- } /*else*/
- if ( gotchild ) { /*performing as a child process*/
- if ( temp2[0] == '&' ) strdel(temp2,0,1);
- for ( r = 23; r <= 25; ++r ) {
- gotoxy(1,r);
- clreol();
- }
- gotoxy(1,23);
- r = system(temp2);
- switch ( r ) {
- case 0:
- break; /*ok*/
- case 1:
- {
- cprintf("%s%c","Invalid function", '\x07');
- cprintf("%s", "..Press a key to continue..");
- ch=getch();
- }
- break;
- case 2:
- {
- cprintf("%s%c","File/path not found", '\x07');
- cprintf("%s", "..Press a key to continue..");
- ch=getch();
- }
- break;
- case 8:
- {
- cprintf("%s%c","Not enough memory to load program", '\x07');
- cprintf("%s", "..Press a key to continue..");
- ch=getch();
- }
- break;
- case 10:
- {
- cprintf("%s%c", "Bad environment (greater than 32K)", '\x07');
- cprintf("%s", "..Press a key to continue..");
- ch=getch();
- }
- break;
- case 11:
- {
- cprintf("%s%c", "Illegal .EXE file format", '\x07');
- cprintf("%s", "..Press a key to continue..");
- ch=getch();
- }
- break;
- default:
- cprintf("%c", '\x07');
- break;
- } /*case*/
- } /*if gotchild*/
- cp = cp->next; /*follow linked list*/
- } /*while*/
- if ( ! gotchild ) {
- fclose(batfile);
- done = TRUE; /*exit and execute batch file*/
- } /*if not gotchild*/
- } /*else doing action*/
- } /*else got good menu*/
- L90:
- ;
- } while ( ! (done) );
-
- if ( color(back3) > 7 ) {
- textcolor(color(fore3) + blink);
- }
- else {
- textcolor(color(fore3));
- }
- textbackground(color(back3));
- border(color(back3));
- clrscr();
- if ( datachanged ) savemenu();
- if ( parmchanged ) saveparm();
- }
-