home *** CD-ROM | disk | FTP | other *** search
- /* README.PRG Vers. 1.0 By Todd Burkey, 6/1/88. */
- /* Version 1.1 6/10/88-Todd Burkey: Added Color selection and Tab support */
- /* Version 1.2 6/19/88-Todd Burkey: Started code setup for menu overlays */
-
- /* The source code and accompany text files (MENU.TRB and README.TRB) must
- always accompany the README.PRG file (ARC'ed as a package). */
-
- /*
- This program shows one use of the POPHELP mechanism (Copyright 1988 by
- Todd Burkey). POPHELP is intended to be a 'clean' way of presenting help
- to users of a program and was also written to demonstrate in source code
- how to do those confusing linea/vdi/etc things that all of our manuals kind
- of gloss over. I am not saying that my methods are proper coding or even
- close, but at least it works. In order to ensure that this code and the
- techniques involved stay accessible to the public at large, I have to make
- the following stipulations:
-
- 1) This program and source code may be freely distributed as long as no
- profits are made in the process (Club Disks of the Month and BBS's are
- excepted, of course.)
- 2) All derivatives of the routines in this code must include this notice
- verbatim and are similarly subject to the conditions in 1, above.
- 3) No warrantees are made as to the usefulness or safety of using this
- code. The user uses it at his/her own risk.
-
- -Todd Burkey "A member of STdNET-The ST developers' Network"
- trb@stag.UUCP
- 3546 Pilgrim Lane
- Plymouth, MN 55441
- */
-
- #include <linea.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <aesbind.h>
- #include <osbind.h>
- #include <vdibind.h>
- #include <bios.h>
-
- #define RESTORE 1
- #define SAVE 2
- #define ONLYTEXT 1
- #define MOREHELP 2
- #define ESC 27
- #define HELP 98
- #define UPARROW 72
- #define DOWNARROW 80
- #define LEFTARROW 75
- #define RIGHTARROW 77
- #define LEFTBUTTON 0x740000L
- #define RIGHTBUTTON 0x750000L
- #define MAX_MENUS 100
-
- /* and now some necessary vdi/aes stuff */
- int h,xy[16],contrl[12],intin[128],ptsin[128],intout[128],ptsout[128];
- int src[11];
- int scr_a[] = { 0, 0, 640, 200, 40, 0, 2, 0, 0, 0 };
- char *oldscr,*newscr,*memblk;
-
- /* and now for the POPMENU related arrays */
- int menu_col[MAX_MENUS+1], /* upper left column number for menu */
- menu_row[MAX_MENUS+1], /* upper left row number for menu */
- menu_fr[MAX_MENUS], /* first character in menu_s for the menu */
- menu_to[MAX_MENUS], /* last character in menu_s for the menu */
- menu_last[MAX_MENUS], /* previous menu that you viewed */
- on_line[MAX_MENUS], /* what line were you last on? */
- menu_rgb[MAX_MENUS+1][4]; /* color rgb map for menu */
- char menu_s[30000];
- int error_cnt=0;
- int which; /* which menu are we on */
- int menu_length, /* length (height) of current menu */
- menu_width, /* width of current menu */
- lc1,lc2,lr1,lr2, /* last corners (col/row) of menu box */
- menu_ptr[24], /* a menu selections' next menu (forward ptr) */
- menu_type[24]; /* type of menu entry...ONLYTEXT or MOREHELP */
- char menu_line[24][130]; /* what you see in the box */
- char help_path[100]; /* tbd...for global path lookup... */
- int menu_s_pos; /* tbd...useful if we use menu overlays */
-
- /* and some stuff I need */
- long tst,vtst;
- int htst,mono,black,blue,red,green;
- int save_col[4];
- long _stksize = 40000L;
- static long patmsk = -1;
-
- main()
- {
- int i;
- color_init();
- ws_init(); /* do all that messy vdi/linea initialization */
- build_help(); /* build the internal help arrays from menu.trb */
- if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x0a); /* set mouse cursor mode */
- if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x14); /* 20 pulses per x move */
- if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x05); /* 5 pulses per y move */
- mon_keys();
- if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x08); /* reset mouse mode to normal */
- for(i=0;i<4;i++) Setcolor(i,save_col[i]);
- }
-
- color_init() /* check resolutions and setup accordingly */
- {
- int i;
- i=Getrez();
- if(i==0) {
- printf("Sorry, Medium or High Res only\n[Hit any key]\n");
- Crawcin();
- exit(1);
- }
- if(i==2) {
- mono=1;
- black='3';
- blue='3';
- red='3';
- green='0';
- }
- else {
- mono=0;
- black='2';
- blue='0';
- red='1';
- green='2';
- }
- for(i=0;i<4;i++) save_col[i]=Setcolor(i,-1);
- for(i=0;i<=MAX_MENUS;i++) { /* setup default colors */
- if(mono) menu_rgb[i][0]=0x777;
- else menu_rgb[i][0]=0x006;
- menu_rgb[i][1]=0x600;
- menu_rgb[i][2]=0x000;
- if(mono) menu_rgb[i][3]=0x000;
- else menu_rgb[i][3]=0x775;
- }
- set_rgb(0);
- }
-
- mon_keys() /* simple loop that waits for a HELP key or Q key */
- {
- while(((tst=Bconin(2))&0xFF)!='Q') {
- tst=tst>>16;
- if(tst==HELP) {
- which=0;
- show_help(1);
- }
- while((Cconis())!=0) Crawcin();
- }
- v_clsvwk(h);
- appl_exit();
- }
-
- set_rgb(m)
- int m;
- {
- Setcolor(0,menu_rgb[m][0]);
- Setcolor(1,menu_rgb[m][1]);
- Setcolor(2,menu_rgb[m][2]);
- Setcolor(3,menu_rgb[m][3]);
- }
-
- draw_help(menu) /* draw the selected help popup */
- int menu;
- {
- int i,j;
- /* First, gather up all of the info for the CURRENT menu to draw */
- menu_length=0;
- if(menu>=MAX_MENUS||menu<0)
- sprintf(menu_line[menu_length++],"ERROR IN MENU.TRB. Menu numbers must be between 0 and 99.");
- else if(menu_fr[menu]<0)
- sprintf(menu_line[menu_length++],"ERROR IN MENU.TRB. Can't Find the menu definition for %d.",menu);
- if(menu_length>0) {
- sprintf(menu_line[menu_length++],"Please fix this problem ASAP. Press the Left Arrow now.");
- menu_width=strlen(menu_line[0]);
- menu_type[0]=menu_type[1]=ONLYTEXT;
- menu=MAX_MENUS;
- menu_col[menu]=4;
- menu_row[menu]=11;
- }
- else if(menu_s[menu_fr[menu]]!='<') {
- for(i=menu_fr[menu],j=0,menu_width=0;i<=menu_to[menu];i++) {
- if(menu_s[i]=='\0') {
- menu_line[menu_length++][j-1]='\0';
- j++;
- if(j>menu_width) menu_width=j;
- j=0;
- }
- else {
- if(j==0&&menu_s[i]=='+') menu_type[menu_length]=MOREHELP;
- else if(j==0&&menu_s[i]=='T') menu_type[menu_length]=ONLYTEXT;
- else if(j==0&&menu_s[i]=='=') {
- menu_ptr[menu_length-1]=atoi(&menu_s[i+2]);
- while(menu_s[i]!='\0'&&i<10000) i++;
- j=0;
- }
- else if(j<=1&&menu_s[i]==':') j++;
- else {
- menu_line[menu_length][j-1]=menu_s[i];
- j++;
- }
- }
- }
- menu_width=menu_width-2;
- }
- else viewfile(menu);
- set_rgb(menu);
- lc1=menu_col[menu];
- lr1=menu_row[menu];
- lc2=lc1+menu_width;
- lr2=lr1+menu_length;
- /* Now, save the part of the screen that we are gonna draw on. */
- screen_it(SAVE,lc1,lr1,lc2,lr2);
- /* and draw the popup */
- fboxcr(lc1,lr1,lc2,lr2);
- boxcr(lc1,lr1,lc2,lr2);
- for(i=0;i<menu_length;i++) {
- if(menu_type[i]==ONLYTEXT) {
- if(mono) printcr(lc1,lr1+i,menu_line[i]); /* modify for slant someday */
- else tprintcr(lc1,lr1+i,menu_line[i]);
- }
- else {
- if(mono) printcr(lc1,lr1+i,menu_line[i]);
- else bprintcr(lc1,lr1+i,menu_line[i]);
- }
- }
- }
-
- erase_help() /* move the stuff we saved to the scratch pad back */
- {
- screen_it(RESTORE,lc1,lr1,lc2,lr2);
- }
-
- hilite_menu(i) /* highlight the selection under the cursor */
- int i;
- {
- if(mono) {
- printcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
- bprintcr(lc1,lr1+i,menu_line[i]);
- }
- else {
- bprintcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
- printcr(lc1,lr1+i,menu_line[i]);
- }
- on_line[which]=i;
- }
-
- show_help(menu) /* recursive routine handling the help popup walking */
- int menu;
- {
- int i,all_text;
- if(which<0) return;
- draw_help(menu);
- on_line[which]=0;
- for(i=0;i<menu_length&&menu_type[i]==ONLYTEXT;i++);
- if(i<menu_length) {
- all_text=0;
- on_line[which]=i;
- if(mono) bprintcr(lc1,lr1+i,menu_line[i]);
- else printcr(lc1,lr1+i,menu_line[i]);
- }
- else all_text=1;
- while(((tst=Bconin(2))&0xFF)!=ESC) {
- htst=tst&0xFF;
- vtst=tst>>16;
- if(!all_text&&which<100&&(tst==RIGHTBUTTON||vtst==RIGHTARROW)) {
- erase_help();
- menu_last[which++]=menu;
- show_help(menu_ptr[on_line[which-1]]);
- if(which<0) return;
- continue;
- }
- else if(which>0&&(tst==LEFTBUTTON||vtst==LEFTARROW)) {
- if(menu>=0) {
- erase_help();
- menu=menu_last[--which];
- draw_help(menu);
- if(menu_type[on_line[which]]!=ONLYTEXT)
- if(mono) bprintcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
- else printcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
- return;
- }
- }
- else if(on_line[which]<menu_length&&(vtst==DOWNARROW||htst=='j')) {
- for(i=on_line[which]+1;i<menu_length&&menu_type[i]==ONLYTEXT;i++);
- if(i<menu_length) hilite_menu(i);
- }
- else if(on_line[which]>0&&(vtst==UPARROW||htst=='k')) {
- for(i=on_line[which]-1;i>0&&menu_type[i]==ONLYTEXT;i--);
- if(menu_type[i]!=ONLYTEXT) hilite_menu(i);
- }
- else {
- if(menu!=0&&vtst!=UPARROW&&vtst!=DOWNARROW&&vtst!=LEFTARROW&&vtst!=RIGHTARROW)
- error_cnt++;
- if(error_cnt>1||vtst==HELP) {
- erase_help();
- error_cnt=0;
- menu_last[which++]=menu;
- show_help(0);
- if(which<0) return;
- continue;
- }
- }
- while((Cconis())!=0) Crawcin();
- }
- erase_help();
- which= -1;
- }
-
- pop_read(s) /* This routine reads a menu file and builds the internal tree */
- char *s;
- {
- char buf[128];
- FILE *ifp;
- int i,j,x,y,r,g,b,on_menu;
- if((ifp=fopen(s,"r"))==NULL) {
- printf("menu configuration file:%s was not found!\n",s);
- exit(99);
- }
- j=menu_s_pos; /* pointer into menu_s array */
- if(ifp!=NULL) {
- while(fgets(buf,128,ifp)!=NULL) {
- if(buf[1]!=':') continue;
- switch(buf[0]) {
- case '<':
- case 'T':
- case '+':
- case '=':
- for(i=0;i<strlen(buf);i++)
- if(buf[i]!='\t') menu_s[j++]=buf[i];
- else {
- x=expand_tab(j);
- for(y=j;y<x;y++) menu_s[j++]=' ';
- }
- menu_s[j-1]='\0';
- break;
- case '#':
- if(j>0) menu_to[on_menu]=j-1;
- on_menu=atoi(&buf[2]);
- if(on_menu>MAX_MENUS) {
- printf("ERROR. Can't define menu. Its' number [%d] is >100...aborting\n",on_menu);
- exit(1);
- }
- menu_fr[on_menu]=j;
- break;
- case 'X':
- menu_col[on_menu]=atoi(&buf[2]);
- break;
- case 'Y':
- menu_row[on_menu]=atoi(&buf[2]);
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- if(strlen(buf)<6) printf("ERROR. RGB menu definition too short: %s\n",buf);
- r=buf[2]-'0';
- g=buf[3]-'0';
- b=buf[4]-'0';
- if(r<0||r>7||g<0||g>7||b<0||b>7)
- printf("ERROR. RGB values incorrect (must be 0-7): %s\n",buf);
- if(on_menu==1)
- for(i=1;i<=MAX_MENUS;i++) menu_rgb[i][buf[0]-'0']=r*256+g*16+b;
- else menu_rgb[on_menu][buf[0]-'0']=r*256+g*16+b;
- break;
- }
- }
- if(j>0) menu_to[on_menu]=j-1;
- fclose(ifp);
- }
- }
-
- build_help() /* this routine reads the menu file and builds the popup tree */
- {
- int i;
- for(i=0;i<MAX_MENUS;i++) menu_fr[i]= -1;
- menu_s_pos=0; /* pointer into menu_s array */
- pop_read("MENU.TRB");
- }
-
- viewfile(menu) /* gather menu information from a file */
- int menu; /* would be nice to modify this to allow paging... :-) */
- { /* Note that we build a fake menu structure from the file */
- int i,j,x,y;
- char ebuf[150],buf[129],s[200];
- FILE *ifp;
- strcpy(s,&menu_s[menu_fr[menu]+2]);
- if ((ifp=fopen(s,"r"))==NULL) { /* throw up a read-only one-liner */
- sprintf(menu_line[0],"Sorry, can't open %s. Press the left arrow.",s);
- menu_length=1;
- menu_width=strlen(menu_line[0]);
- menu_type[0]=ONLYTEXT;
- return;
- }
- menu_length=0;
- menu_width=0;
- while((menu_length+menu_row[menu])<24&&fgets(buf,128,ifp)!=NULL) {
- j=0;
- for(i=0;i<strlen(buf);i++)
- if(buf[i]!='\t') ebuf[j++]=buf[i];
- else {
- x=expand_tab(j);
- for(y=j;y<x;y++) ebuf[j++]=' ';
- }
- ebuf[j-1]='\0';
- strcpy(menu_line[menu_length],ebuf);
- menu_type[menu_length++]=ONLYTEXT;
- if(j>menu_width) menu_width=j;
- }
- fclose(ifp);
- }
-
- ws_init()
- {
- int ii,i,work_in[11],work_out[57];
- linea0(); /* yep, we are going to try linea stuff */
- src[0]=0;src[1]=0; /* general setup for doing vdi stuff follows*/
- work_in[0]=1;
- for(i=1;i<10;i++) work_in[i]=1;
- work_in[10]=2;
- appl_init();
- h=graf_handle(&ii,&ii,&ii,&ii);
- graf_mouse(256,NULL);
- clear_screen();
- v_opnvwk(work_in,&h,work_out);
- src[2]=work_out[0]+1;
- src[3]=work_out[1]+1;
- src[4]=src[2]>>4;
- src[5]=0;
- if(mono) src[6]=1;
- else src[6]=2;
- if(mono) { /* modify fdb for the vro_cpyfm */
- scr_a[3]=400; /* 400 pixels high */
- scr_a[6]=1; /* 1 bit plane */
- }
- memblk=(char *)Malloc(32*1024L); /* alloc 32k */
- oldscr=(char *) Physbase(); /* where is screen */
- newscr=(char *) (((long) memblk+0xFFL)& ~(0xFFL)); /* assign paste */
- *((long *)src)=(long) oldscr; /* assign ptr to screen */
- *((long *)scr_a)=(long) newscr; /* assign ptr to paste */
- v_hide_c(h);
- draw_cover();
- }
-
- clear_screen()
- {
- v_clrwk(h);
- }
-
- draw_cover() /* display a setup (cover) page */
- {
- char buf[129];
- FILE *ifp;
- int i;
- i=0;
- clear_screen();
- if((ifp=fopen("README.TRB","r"))==NULL)
- printf("README.TRB not found! If MENU.TRB exists, press HELP for more info.\n");
- else {
- printf("\33f\33Y%c%c\33pReady? Press The HELP key for more info, then ESC and Q to quit\33q",56,42);
- while(fgets(buf,128,ifp)!=NULL&&i<24) {
- if(buf[0]=='/') continue;
- if(i==0) printf("\33Y %s",buf);
- else printf("%s",buf);
- i++;
- }
- fclose(ifp);
- }
- }
-
- tprintcr(c,r,string) /* print a red string at <col,row> */
- int c,r;
- char *string;
- {
- r=r+32;
- c=c+32;
- printf("\33Y%c%c\33c%c\33p%s\33q\33c%c\n",r,c,red,string,blue);
- }
-
- bprintcr(c,r,string) /* print a 'bold/reverse video' string at <col,row> */
- int c,r;
- char *string;
- {
- r=r+32;
- c=c+32;
- printf("\33Y%c%c\33p%s\33q\n",r,c,string);
- }
-
- printcr(c,r,string) /* print a string at <column,row> */
- int c,r;
- char *string;
- {
- r=r+32;
- c=c+32;
- printf("\33Y%c%c%s\n",r,c,string);
- }
-
- fboxcr(c1,r1,c2,r2) /* draw a shadow box and then an overlay one. */
- int c1,r1,c2,r2; /* using linea for the fun of it */
- {
- LNMASK= -1;
- WMODE= 0;
- CLIP=0;
- PATPTR=&patmsk;
- PATMSK=1;
- if(mono) COLBIT0=1;
- else {
- COLBIT0=0;
- COLBIT1=1;
- }
- X1=(c1<<3)+5;
- X2=(c2<<3)+7;
- if(mono) {
- Y1=(r1<<4)-10;
- Y2=(r2<<4)-6;
- }
- else {
- Y1=(r1<<3)-5;
- Y2=(r2<<3)-3;
- }
- linea5(); /* lot of work for a stupid rectangle, but this shows linea */
- if(mono) COLBIT0=0;
- else COLBIT0=1;
- X1=(c1<<3)-2;
- X2=(c2<<3);
- if(mono) {
- Y1=(r1<<4)-2;
- Y2=(r2<<4);
- }
- else {
- Y1=(r1<<3)-1;
- Y2=(r2<<3);
- }
- linea5();
- boxcr(c1,r1,c2,r2);
- }
-
- boxcr(c1,r1,c2,r2) /* now draw a hollow box around the top filled...*/
- int c1,r1,c2,r2;
- {
- xy[0]=xy[6]=xy[8]=(c1<<3)-3;
- xy[2]=xy[4]=(c2<<3)+1;
- if(mono==1) {
- xy[1]=xy[3]=xy[9]=(r1<<4)-3;
- xy[5]=xy[7]=(r2<<4)+1;
- }
- else {
- xy[1]=xy[3]=xy[9]=(r1<<3)-2;
- xy[5]=xy[7]=(r2<<3)+1;
- }
- v_pline(h,5,xy);
- }
-
- screen_it(wh,c1,r1,c2,r2) /* do a simple blit to or from the paste */
- int wh,c1,r1,c2,r2; /* columns and rows in cursor coordinates */
- {
- int lx,ux,ly,uy;
- lx=(c1<<3)-4;
- ux=(c2<<3)+7;
- if(mono==1) {
- ly=(r1<<4) - 16;
- uy=(r2<<4)+4;
- if(uy>399) uy=399;
- }
- else {
- ly=(r1<<3) - 8;
- uy=(r2<<3)+2;
- if(uy>199) uy=199;
- }
- if(lx<0) lx=0;
- if(ly<0) ly=0;
- if(ux>639) ux=639;
- xy[1]=xy[5]=ly; /* uly */
- xy[3]=xy[7]=uy; /* lry */
- xy[0]=xy[4]=lx; /* ulx */
- xy[2]=xy[6]=ux; /* lrx */
- if(wh==SAVE)
- vro_cpyfm(h,3,xy,src,scr_a);
- else
- vro_cpyfm(h,3,xy,scr_a,src);
- }
-
- int expand_tab(index) /* expand a tab out, calculating new position */
- int index;
- {
- do
- index++;
- while ((index&0x07)!=0);
- return(index);
- }
-
-