[comp.sources.atari.st] v01i059: readme12 -- online help system

koreth@ssyx.ucsc.edu (Steven Grimm) (06/23/88)

Submitted-by: ucbvax!ihnp4!stag!trb (Todd Burkey)
Posting-number: Volume 1, Issue 59
Archive-name: readme12

The following is the source code and executable for a README
application that implements my new POPHELP mechanism. Full source
code is included for README (MW C) and it runs in both Medium Res
(RGB) and High Res (mono). A menu configuration file that describes
POPHELP is also included (and automatically presented to the user
when they run README.PRG).

The program is self documenting (it would be silly if it wasn't).
My primary goal in writing the POPHELP routines was to beef up
HDSCAN's interactive help and to lay the groundwork for full popup
menu control for users of HDSCAN. It ended up to be such short and
simple code that I decided to put it out for others to use, add to
their own programs, or simply learn some coding techniques from.
The code has been implemented in the next version of HDSCAN (took
about 2 hours to integrate it) and does tend to snaz up your application
some.  One of the local developers has even created a README pophelp
configuration file for Mark Johnson C. Enjoy.

Some features of POPHELP:
  1) External Help file driven (think of it as a help resource file).
     Can also be fully integrated into the application code.
  2) Allows context sensitive help applications to be easily written.
  3) Users can wander through the help popups via arrow keys or the
     mouse.
  4) The popups are very fast and consist of selectable and
     non-selectable text in shadowed popup boxes.
  5) The implementor can vary screen color from popup to popup.
  6) External files can be 'fed' into a popup menu (saving on memory
     for little used/accessed help topics).
Some features of README:
  1) Originally intended as a test vehicle for checking out the
     POPHELP routines, I actually am using README to replace my README
     files for HDSCAN and DISKSCAN. Much cleaner user interface.
  2) Allows a user defined 'front page' from which the HELP key can be
     pressed to allow a user to 'learn' about an application in a
     logical fashion.

   -Todd Burkey     "A member of STdNET - The ST developers' Network"
    trb@stag.UUCP

-------------------------------------------------------------
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  README12.C
#	  MENU.TRB
#	  README.TRB
#	  SAMPLE.TXT
#
sed 's/^X//' << 'SHAR_EOF' > README12.C &&
X               /* README.PRG Vers. 1.0 By Todd Burkey, 6/1/88. */
X/* Version 1.1 6/10/88-Todd Burkey: Added Color selection and Tab support */
X/* Version 1.2 6/19/88-Todd Burkey: Started code setup for menu overlays  */
X
X/* The source code and accompany text files (MENU.TRB and README.TRB) must
X   always accompany the README.PRG file (ARC'ed as a package).             */
X
X/*
X   This program shows one use of the POPHELP mechanism (Copyright 1988 by
X   Todd Burkey). POPHELP is intended to be a 'clean' way of presenting help
X   to users of a program and was also written to demonstrate in source code
X   how to do those confusing linea/vdi/etc things that all of our manuals kind
X   of gloss over. I am not saying that my methods are proper coding or even
X   close, but at least it works. In order to ensure that this code and the
X   techniques involved stay accessible to the public at large, I have to make
X   the following stipulations:
X
X     1) This program and source code may be freely distributed as long as no
X        profits are made in the process (Club Disks of the Month and BBS's are
X        excepted, of course.)
X     2) All derivatives of the routines in this code must include this notice
X        verbatim and are similarly subject to the conditions in 1, above.
X     3) No warrantees are made as to the usefulness or safety of using this
X        code. The user uses it at his/her own risk.
X
X         -Todd Burkey    "A member of STdNET-The ST developers' Network"
X          trb@stag.UUCP
X          3546 Pilgrim Lane
X          Plymouth, MN 55441
X*/
X
X#include <linea.h>
X#include <ctype.h>
X#include <stdio.h>
X#include <aesbind.h>
X#include <osbind.h>
X#include <vdibind.h>
X#include <bios.h>
X
X#define RESTORE 1
X#define SAVE 2
X#define ONLYTEXT 1
X#define MOREHELP 2
X#define ESC 27
X#define HELP 98
X#define UPARROW 72
X#define DOWNARROW 80
X#define LEFTARROW 75
X#define RIGHTARROW 77
X#define LEFTBUTTON 0x740000L
X#define RIGHTBUTTON 0x750000L
X#define MAX_MENUS 100
X
X/* and now some necessary vdi/aes stuff */
Xint h,xy[16],contrl[12],intin[128],ptsin[128],intout[128],ptsout[128];
Xint src[11];
Xint scr_a[] = {  0, 0, 640, 200, 40, 0, 2, 0, 0, 0 };
Xchar *oldscr,*newscr,*memblk;
X
X/* and now for the POPMENU related arrays */
Xint menu_col[MAX_MENUS+1],     /* upper left column number for menu */
X    menu_row[MAX_MENUS+1],     /* upper left row number for menu */
X    menu_fr[MAX_MENUS],        /* first character in menu_s for the menu */
X    menu_to[MAX_MENUS],        /* last character in menu_s for the menu */
X    menu_last[MAX_MENUS],      /* previous menu that you viewed */
X    on_line[MAX_MENUS],        /* what line were you last on? */
X    menu_rgb[MAX_MENUS+1][4];  /* color rgb map for menu */
Xchar menu_s[30000];
Xint error_cnt=0;
Xint which;                     /* which menu are we on */
Xint menu_length,               /* length (height) of current menu */
X    menu_width,                /* width of current menu */
X    lc1,lc2,lr1,lr2,           /* last corners (col/row) of menu box */
X    menu_ptr[24],              /* a menu selections' next menu (forward ptr) */
X    menu_type[24];             /* type of menu entry...ONLYTEXT or MOREHELP */
Xchar menu_line[24][130];       /* what you see in the box */
Xchar help_path[100];           /* tbd...for global path lookup... */
Xint menu_s_pos;                /* tbd...useful if we use menu overlays */
X
X/* and some stuff I need */
Xlong tst,vtst;
Xint htst,mono,black,blue,red,green;
Xint save_col[4];
Xlong _stksize = 40000L;    
Xstatic long patmsk = -1;
X
Xmain()
X{
X  int i;
X  color_init();
X  ws_init();             /* do all that messy vdi/linea initialization */
X  build_help();          /* build the internal help arrays from menu.trb */
X  if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x0a);  /* set mouse cursor mode */
X  if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x14);  /* 20 pulses per x move */
X  if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x05);  /* 5 pulses per y move */
X  mon_keys();
X  if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x08);  /* reset mouse mode to normal */
X  for(i=0;i<4;i++) Setcolor(i,save_col[i]);
X  }
X
Xcolor_init()   /* check resolutions and setup accordingly */
X{
X  int i;
X  i=Getrez();
X  if(i==0) {
X    printf("Sorry, Medium or High Res only\n[Hit any key]\n");
X    Crawcin();
X    exit(1);
X    }
X  if(i==2) {
X     mono=1;
X     black='3';
X     blue='3';
X     red='3';
X     green='0';
X     }
X  else {
X    mono=0;
X    black='2';
X    blue='0';
X    red='1';
X    green='2';
X    }
X  for(i=0;i<4;i++) save_col[i]=Setcolor(i,-1);
X  for(i=0;i<=MAX_MENUS;i++) {          /* setup default colors */
X    if(mono) menu_rgb[i][0]=0x777;
X    else     menu_rgb[i][0]=0x006;
X    menu_rgb[i][1]=0x600;
X    menu_rgb[i][2]=0x000;
X    if(mono) menu_rgb[i][3]=0x000;
X    else     menu_rgb[i][3]=0x775;
X    }
X  set_rgb(0);
X  }
X
Xmon_keys()   /* simple loop that waits for a HELP key or Q key */
X{
X  while(((tst=Bconin(2))&0xFF)!='Q') {
X    tst=tst>>16;
X    if(tst==HELP) {
X      which=0;
X      show_help(1);
X      }
X    while((Cconis())!=0) Crawcin();
X    }
X  v_clsvwk(h);
X  appl_exit();
X  }
X
Xset_rgb(m)
Xint m;
X{
X  Setcolor(0,menu_rgb[m][0]);
X  Setcolor(1,menu_rgb[m][1]);
X  Setcolor(2,menu_rgb[m][2]);
X  Setcolor(3,menu_rgb[m][3]);
X  }
X
Xdraw_help(menu)  /* draw the selected help popup */
Xint menu;
X{
X  int i,j;
X/* First, gather up all of the info for the CURRENT menu to draw */
X  menu_length=0;
X  if(menu>=MAX_MENUS||menu<0)
X    sprintf(menu_line[menu_length++],"ERROR IN MENU.TRB. Menu numbers must be between 0 and 99.");
X  else if(menu_fr[menu]<0)
X    sprintf(menu_line[menu_length++],"ERROR IN MENU.TRB. Can't Find the menu definition for %d.",menu);
X  if(menu_length>0) {
X    sprintf(menu_line[menu_length++],"Please fix this problem ASAP. Press the Left Arrow now.");
X    menu_width=strlen(menu_line[0]);
X    menu_type[0]=menu_type[1]=ONLYTEXT;
X    menu=MAX_MENUS;
X    menu_col[menu]=4;
X    menu_row[menu]=11;
X    }
X  else if(menu_s[menu_fr[menu]]!='<') {
X    for(i=menu_fr[menu],j=0,menu_width=0;i<=menu_to[menu];i++) {
X      if(menu_s[i]=='\0') {
X        menu_line[menu_length++][j-1]='\0';
X        j++;
X        if(j>menu_width) menu_width=j;
X        j=0;
X        }
X      else {
X        if(j==0&&menu_s[i]=='+') menu_type[menu_length]=MOREHELP;
X        else if(j==0&&menu_s[i]=='T') menu_type[menu_length]=ONLYTEXT;
X        else if(j==0&&menu_s[i]=='=') {
X          menu_ptr[menu_length-1]=atoi(&menu_s[i+2]);
X          while(menu_s[i]!='\0'&&i<10000) i++;
X          j=0;
X          }
X        else if(j<=1&&menu_s[i]==':') j++;
X        else {
X          menu_line[menu_length][j-1]=menu_s[i];
X          j++;
X          }
X        }
X      }
X    menu_width=menu_width-2;
X    }
X  else viewfile(menu);
X  set_rgb(menu);
X  lc1=menu_col[menu];
X  lr1=menu_row[menu];
X  lc2=lc1+menu_width;
X  lr2=lr1+menu_length;
X/* Now, save the part of the screen that we are gonna draw on. */
X  screen_it(SAVE,lc1,lr1,lc2,lr2);
X/* and draw the popup */
X  fboxcr(lc1,lr1,lc2,lr2);
X  boxcr(lc1,lr1,lc2,lr2); 
X  for(i=0;i<menu_length;i++) {
X    if(menu_type[i]==ONLYTEXT) {
X      if(mono) printcr(lc1,lr1+i,menu_line[i]); /* modify for slant someday */
X      else    tprintcr(lc1,lr1+i,menu_line[i]);
X      }
X    else {
X      if(mono) printcr(lc1,lr1+i,menu_line[i]);
X      else bprintcr(lc1,lr1+i,menu_line[i]);
X      }
X    }
X  }
X
Xerase_help()   /* move the stuff we saved to the scratch pad back */
X{
X  screen_it(RESTORE,lc1,lr1,lc2,lr2);
X  }
X
Xhilite_menu(i)   /* highlight the selection under the cursor */
Xint i;
X{
X  if(mono) {
X    printcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
X    bprintcr(lc1,lr1+i,menu_line[i]);
X    }
X  else {
X    bprintcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
X    printcr(lc1,lr1+i,menu_line[i]);
X    }
X  on_line[which]=i;
X  }
X
Xshow_help(menu)  /* recursive routine handling the help popup walking */
Xint menu;
X{
X  int i,all_text;
X  if(which<0) return;
X  draw_help(menu);
X  on_line[which]=0;
X  for(i=0;i<menu_length&&menu_type[i]==ONLYTEXT;i++);
X  if(i<menu_length) {
X    all_text=0;
X    on_line[which]=i;
X    if(mono) bprintcr(lc1,lr1+i,menu_line[i]);
X    else      printcr(lc1,lr1+i,menu_line[i]);
X    }
X  else all_text=1;
X  while(((tst=Bconin(2))&0xFF)!=ESC) {
X    htst=tst&0xFF;
X    vtst=tst>>16;
X    if(!all_text&&which<100&&(tst==RIGHTBUTTON||vtst==RIGHTARROW)) {
X      erase_help();
X      menu_last[which++]=menu;
X      show_help(menu_ptr[on_line[which-1]]);
X      if(which<0) return;
X      continue;
X      }
X    else if(which>0&&(tst==LEFTBUTTON||vtst==LEFTARROW)) {
X      if(menu>=0) {
X        erase_help();
X        menu=menu_last[--which];
X        draw_help(menu);
X        if(menu_type[on_line[which]]!=ONLYTEXT) 
X          if(mono) bprintcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
X          else      printcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
X        return;
X        }
X      }
X    else if(on_line[which]<menu_length&&(vtst==DOWNARROW||htst=='j')) {
X      for(i=on_line[which]+1;i<menu_length&&menu_type[i]==ONLYTEXT;i++);
X      if(i<menu_length) hilite_menu(i);
X      }
X    else if(on_line[which]>0&&(vtst==UPARROW||htst=='k')) {
X      for(i=on_line[which]-1;i>0&&menu_type[i]==ONLYTEXT;i--);
X      if(menu_type[i]!=ONLYTEXT) hilite_menu(i);
X      }
X    else {
X      if(menu!=0&&vtst!=UPARROW&&vtst!=DOWNARROW&&vtst!=LEFTARROW&&vtst!=RIGHTARROW)
X        error_cnt++;
X      if(error_cnt>1||vtst==HELP) {
X        erase_help();
X        error_cnt=0;
X        menu_last[which++]=menu;
X        show_help(0);
X        if(which<0) return;
X        continue;
X        }
X      }
X    while((Cconis())!=0) Crawcin();
X    }
X  erase_help();
X  which= -1;
X  }
X
Xpop_read(s) /* This routine reads a menu file and builds the internal tree */
Xchar *s;
X{
X  char buf[128];
X  FILE *ifp;
X  int i,j,x,y,r,g,b,on_menu;
X  if((ifp=fopen(s,"r"))==NULL) {
X    printf("menu configuration file:%s was not found!\n",s);
X    exit(99);
X    }
X  j=menu_s_pos;                /* pointer into menu_s array */
X  if(ifp!=NULL) {
X    while(fgets(buf,128,ifp)!=NULL) {
X      if(buf[1]!=':') continue;
X      switch(buf[0]) {
X        case '<':
X        case 'T':
X        case '+':
X        case '=':
X          for(i=0;i<strlen(buf);i++)
X            if(buf[i]!='\t') menu_s[j++]=buf[i];
X            else {
X              x=expand_tab(j);
X              for(y=j;y<x;y++) menu_s[j++]=' ';
X              }
X          menu_s[j-1]='\0';
X          break;
X        case '#':
X          if(j>0) menu_to[on_menu]=j-1;
X          on_menu=atoi(&buf[2]);
X          if(on_menu>MAX_MENUS) {
X            printf("ERROR. Can't define menu. Its' number [%d] is >100...aborting\n",on_menu);
X            exit(1);
X            }
X          menu_fr[on_menu]=j;
X          break;
X        case 'X':
X          menu_col[on_menu]=atoi(&buf[2]);
X          break;
X        case 'Y':
X          menu_row[on_menu]=atoi(&buf[2]);
X          break;
X        case '0':
X        case '1':
X        case '2':
X        case '3':
X          if(strlen(buf)<6) printf("ERROR. RGB menu definition too short: %s\n",buf);
X          r=buf[2]-'0';
X          g=buf[3]-'0';
X          b=buf[4]-'0';
X          if(r<0||r>7||g<0||g>7||b<0||b>7)
X            printf("ERROR. RGB values incorrect (must be 0-7): %s\n",buf);
X          if(on_menu==1)
X            for(i=1;i<=MAX_MENUS;i++) menu_rgb[i][buf[0]-'0']=r*256+g*16+b;
X          else menu_rgb[on_menu][buf[0]-'0']=r*256+g*16+b;
X          break;
X        }
X      }
X    if(j>0) menu_to[on_menu]=j-1;
X    fclose(ifp);
X    }
X  }
X
Xbuild_help() /* this routine reads the menu file and builds the popup tree */
X{
X  int i;
X  for(i=0;i<MAX_MENUS;i++) menu_fr[i]= -1;
X  menu_s_pos=0;                /* pointer into menu_s array */
X  pop_read("MENU.TRB");
X  }
X
Xviewfile(menu)  /* gather menu information from a file */
Xint menu;       /* would be nice to modify this to allow paging... :-) */
X{               /* Note that we build a fake menu structure from the file */
X  int i,j,x,y;
X  char ebuf[150],buf[129],s[200];
X  FILE *ifp;
X  strcpy(s,&menu_s[menu_fr[menu]+2]);
X  if ((ifp=fopen(s,"r"))==NULL) {   /* throw up a read-only one-liner */
X    sprintf(menu_line[0],"Sorry, can't open %s. Press the left arrow.",s);
X    menu_length=1;
X    menu_width=strlen(menu_line[0]);
X    menu_type[0]=ONLYTEXT;
X    return;
X    }
X  menu_length=0;
X  menu_width=0;
X  while((menu_length+menu_row[menu])<24&&fgets(buf,128,ifp)!=NULL) {
X    j=0;
X    for(i=0;i<strlen(buf);i++)
X      if(buf[i]!='\t') ebuf[j++]=buf[i];
X      else {
X        x=expand_tab(j);
X        for(y=j;y<x;y++) ebuf[j++]=' ';
X        }
X    ebuf[j-1]='\0';
X    strcpy(menu_line[menu_length],ebuf);
X    menu_type[menu_length++]=ONLYTEXT;
X    if(j>menu_width) menu_width=j;
X    }
X  fclose(ifp);
X  }
X
Xws_init()
X{
X   int ii,i,work_in[11],work_out[57];
X   linea0();             /* yep, we are going to try linea stuff */
X   src[0]=0;src[1]=0;    /* general setup for doing vdi stuff follows*/
X   work_in[0]=1;
X   for(i=1;i<10;i++) work_in[i]=1;
X   work_in[10]=2;
X   appl_init();
X   h=graf_handle(&ii,&ii,&ii,&ii);
X   graf_mouse(256,NULL);
X   clear_screen();
X   v_opnvwk(work_in,&h,work_out);
X   src[2]=work_out[0]+1;
X   src[3]=work_out[1]+1;
X   src[4]=src[2]>>4;
X   src[5]=0;
X   if(mono) src[6]=1;
X   else     src[6]=2;
X   if(mono) {        /* modify fdb for the vro_cpyfm */
X     scr_a[3]=400;   /* 400 pixels high */
X     scr_a[6]=1;     /* 1 bit plane */
X     }
X   memblk=(char *)Malloc(32*1024L);                      /* alloc 32k */
X   oldscr=(char *) Physbase();                           /* where is screen */
X   newscr=(char *) (((long) memblk+0xFFL)& ~(0xFFL));    /* assign paste */
X   *((long *)src)=(long) oldscr;     /* assign ptr to screen */
X   *((long *)scr_a)=(long) newscr;   /* assign ptr to paste */
X   v_hide_c(h);
X   draw_cover();
X   }
X  
Xclear_screen()
X{
X  v_clrwk(h);
X  }
X
Xdraw_cover()  /* display a setup (cover) page */
X{
X  char buf[129];
X  FILE *ifp;
X  int i;
X  i=0;
X  clear_screen();
X  if((ifp=fopen("README.TRB","r"))==NULL)
X    printf("README.TRB not found! If MENU.TRB exists, press HELP for more info.\n");
X  else {
X    printf("\33f\33Y%c%c\33pReady? Press The HELP key for more info, then ESC and Q to quit\33q",56,42);
X    while(fgets(buf,128,ifp)!=NULL&&i<24) {
X      if(buf[0]=='/') continue;
X      if(i==0) printf("\33Y  %s",buf);
X      else    printf("%s",buf);
X      i++;
X      }
X    fclose(ifp);
X    }
X  }
X 
Xtprintcr(c,r,string)  /* print a red string at <col,row> */
Xint c,r;
Xchar *string;
X{
X  r=r+32;
X  c=c+32;
X  printf("\33Y%c%c\33c%c\33p%s\33q\33c%c\n",r,c,red,string,blue);
X  }
X
Xbprintcr(c,r,string)  /* print a 'bold/reverse video' string at <col,row> */
Xint c,r;
Xchar *string;
X{
X  r=r+32;
X  c=c+32;
X  printf("\33Y%c%c\33p%s\33q\n",r,c,string);
X  }
X
Xprintcr(c,r,string)  /* print a string at <column,row> */
Xint c,r;
Xchar *string;
X{
X  r=r+32;
X  c=c+32;
X  printf("\33Y%c%c%s\n",r,c,string);
X  }
X
Xfboxcr(c1,r1,c2,r2)  /* draw a shadow box and then an overlay one. */
Xint c1,r1,c2,r2;     /* using linea for the fun of it */
X{
X  LNMASK= -1;
X  WMODE= 0;
X  CLIP=0;
X  PATPTR=&patmsk;
X  PATMSK=1;
X  if(mono) COLBIT0=1;
X  else {
X    COLBIT0=0;
X    COLBIT1=1;
X    }
X  X1=(c1<<3)+5;
X  X2=(c2<<3)+7;
X  if(mono) {
X    Y1=(r1<<4)-10;
X    Y2=(r2<<4)-6;
X    }
X  else {
X    Y1=(r1<<3)-5;
X    Y2=(r2<<3)-3;
X    }
X  linea5();     /* lot of work for a stupid rectangle, but this shows linea */
X  if(mono) COLBIT0=0;
X  else     COLBIT0=1;
X  X1=(c1<<3)-2;
X  X2=(c2<<3);
X  if(mono) {
X    Y1=(r1<<4)-2;
X    Y2=(r2<<4);
X    }
X  else {
X    Y1=(r1<<3)-1;
X    Y2=(r2<<3);
X    }
X  linea5();
X  boxcr(c1,r1,c2,r2);
X  }
X
Xboxcr(c1,r1,c2,r2)   /* now draw a hollow box around the top filled...*/
Xint c1,r1,c2,r2;
X{
X  xy[0]=xy[6]=xy[8]=(c1<<3)-3;
X  xy[2]=xy[4]=(c2<<3)+1;
X  if(mono==1) {
X    xy[1]=xy[3]=xy[9]=(r1<<4)-3;
X    xy[5]=xy[7]=(r2<<4)+1;
X    }
X  else {
X    xy[1]=xy[3]=xy[9]=(r1<<3)-2;
X    xy[5]=xy[7]=(r2<<3)+1;
X    }
X  v_pline(h,5,xy);
X  }
X
Xscreen_it(wh,c1,r1,c2,r2)  /* do a simple blit to or from the paste */
Xint wh,c1,r1,c2,r2;        /* columns and rows in cursor coordinates */
X{
X  int lx,ux,ly,uy;
X  lx=(c1<<3)-4;
X  ux=(c2<<3)+7;
X  if(mono==1) {
X    ly=(r1<<4) - 16;
X    uy=(r2<<4)+4;
X    if(uy>399) uy=399;
X    }
X  else {
X    ly=(r1<<3) - 8;
X    uy=(r2<<3)+2;
X    if(uy>199) uy=199;
X    }
X  if(lx<0) lx=0;
X  if(ly<0) ly=0;
X  if(ux>639) ux=639;
X  xy[1]=xy[5]=ly;      /* uly */
X  xy[3]=xy[7]=uy;      /* lry */
X  xy[0]=xy[4]=lx;      /* ulx */
X  xy[2]=xy[6]=ux;      /* lrx */
X  if(wh==SAVE)
X    vro_cpyfm(h,3,xy,src,scr_a);
X  else
X    vro_cpyfm(h,3,xy,scr_a,src);
X  }
X
Xint expand_tab(index)       /* expand a tab out, calculating new position */
Xint index;
X{
X  do
X    index++;
X  while ((index&0x07)!=0);
X  return(index); 
X  }
X
SHAR_EOF
chmod 0600 README12.C || echo "restore of README12.C fails"
sed 's/^X//' << 'SHAR_EOF' > MENU.TRB &&
X*      SAMPLE MENU TREE FOR POPHELP (Todd Burkey/5-30-88)      */
X/* menu for level 0 help */
X#:0
XX:20
XY:2
XT:    POPHELP By Todd Burkey
XT:
XT:Uh-oh. You need HELP for POPHELP?
XT:OK, the first thing to remember is
XT:that in POPHELP, you really only
XT:need to use the four arrow keys
XT:and the ESC key. The up and down
XT:arrows will move you up and down in
XT:the current pop-up...but only when
XT:there is selectable (blue) text in
XT:the popup. Note that this popup has
XT:NO selectable text...you can just
XT:read it and exit. Which brings us
XT:to the left and right arrow keys.
XT:The right key gets you into a menu,
XT:while the left key moves you back
XT:out of a menu. The ESC key? It gets
XT:you out of the popups altogether.
XT:You can press the LEFT ARROW now.
X#:1
XX:5
XY:15
XT:WELCOME TO POPHELP
X+:HELP ON POPHELP   
X=:3
X+:POPHELP MANIFESTO 
X=:40
X+:Who made this mess
X=:41
X+:ABOUT README      
X=:50
X+:Some Error Testing
X=:42
X+:Other menu #4     
X=:4
X+:Other Menu #6     
X=:6
X
X#:50
XX:4
XY:4
X1:530
XT:README is a generic application that I hope you find useful in setting
XT:up useful on-line documentation for programs you develop. Feel free to
XT:give out copies of README to others who are learning C or who you feel
XT:could use a better help mechanism. I will try to keep the pophelp file
XT:formats upwards compatible, so keep your eyes open for future releases
XT:of improved versions of this program.
X
X#:40
XX:2
XY:4
XT:This program shows one use of the POPHELP mechanism (Copyright 1988 by
XT:Todd Burkey). POPHELP is intended to be a 'clean' way of presenting help
XT:to users of a program and was also written to demonstrate in source code
XT:how to do those confusing linea/vdi/etc things that all of our books kind
XT:of gloss over. I am not saying that my methods are proper coding or even
XT:close, but at least it works. In order to ensure that this code and the
XT:techniques involved stay accessible to the public at large, I have to
XT:make the following stipulations:
XT: 
XT: 1) This program and source code may be freely distributed as long as no
XT:    profits are made in the process (Club Disks of the Month and BBSs are
XT:    excepted, of course.)
XT: 2) All derivatives of the routines in this code must include this notice
XT:    verbatim and are similarly subject to the conditions in 1, above.
XT: 3) No warrantees are made as to the usefulness or safety of using this
XT:    code. The user uses it at his/her own risk.
X
X#:41
X1:030
X2:540
XX:14
XY:15
XT: Todd Burkey                 A member of STdNET
XT: 3546 Pilgrim Lane        The ST developers' Network 
XT: Plymouth, MN 55441            (trb@stag.UUCP)
X
X#:42
XX:10
XY:6
XT:  SIMPLE TESTING  
X+:Look at sample.txt
X=:10
X+:Look at bad file  
X=:11
X+:Open Menu >100    
X=:120
X+:Menu Doesn't exist
X=:88
X+:Goto myself (loop)
X=:42
X
X/* Real help for POPHELP */
X#:3
XX:12
XY:8
XT:GETTING STARTED
X+:Moving Around  
X=:22
X+:Some Comments  
X=:23
X+:Technical Info 
X=:26
X
X#:26
XX:30
XY:10
X+:MENU.TRB Format
X=:27
X+:COLOR Tables   
X=:28
X
X#:27
XX:3
XY:4
XT:The file MENU.TRB is processed by POPHELP's build_menu routine and
XT:drives the entire menu structure of POPHELP. The format of MENU.TRB
XT:is very simple. For example, the following is a sample 2 level menu
XT:with comments (note the comments can't really be part of the line):
XT:#:1             <-we are defining menu # 1
XT:X:10            <-the popup box will start at cursor column 10
XT:Y:4             <-and at cursor row number 4
XT:T:WELCOME       <-just some text to put in red (color #1)
XT:+:More Help     <-text for another menu selection
XT:=:2             <-go to menu 2 when the above text is selected
XT:#:2             <-all done with menu 1, so lets define menu 2 now
XT:X:5             <-new coordinates
XT:Y:6             <-new coordinates
XT:1:070           <-redefine color 1 (the text) to be green (RGB)
XT:<:afile.txt     <-menu 2 popup text is read from a file 
X
X#:60
XX:20
XY:8
X1:530
X2:053
XT:For RGB users only 
XT:  You were warned  
X+:Some soft colors   
X=:61
X+:Some Putrid ones   
X=:62
X+:Late night colors  
X=:63
X
X#:61
XX:5
XY:3
X0:054
X1:410
X2:046
X3:222
XT:Pastels?
XT:0:054
XT:1:500
XT:2:066
XT:3:333
X
X#:62
XX:5
XY:3
X0:070
X1:770
X2:077
X3:707
XT:Putrid
XT:0:070
XT:1:770
XT:2:077
XT:3:707
X
X#:63
XX:5
XY:3
X0:000
X1:700
X2:007
X3:770
XT:Brighter
XT:0:000
XT:1:700
XT:2:007
XT:3:770
X
X#:28
XX:2
XY:4
XT:Colors can be changed from the default setup dynamically within the menus,
XT:but extreme care should be taken so you don't screw things up for people
XT:who use monochrome monitors. The technique is quite simple. Within the
XT:MENU.TRB file, include the following fields when you want a new color:
XT:0:006          <--change color 0 to light blue (normal background)
XT:1:600          <--change color 1 to red (non-selectable text)
XT:2:000          <--change color 2 to black (for the shadow)
XT:3:775          <--change color 3 to off white (popup background).
XT:Note that the default color can be over-ridden by specifying a new color
XT:for menu # 1 (the first popup that is displayed by POPHELP).
X+:Some sample colors maps.
X=:60
X
X#:22
XX:14
XY:10
X+:ARROW KEYS 
X=:24
X+:HOW TO QUIT
X=:25
X
X#:25
XX:40
XY:12
XT:1) Press the ESC key.  This takes
XT:   you out of the help selection.
XT:2) Press the Q (not q) key. This
XT:   exits you from the demo.
X
X#:24
XX:30
XY:12
XT:RIGHT ARROW = Select the hilited menu  
XT:LEFT ARROW  = Move to menu we came from
XT:UP ARROW    = Move up in the menu list 
XT:DOWN ARROW  = Move down in the list    
X
X#:23
XX:15
XY:11
XT:POPHELP is a simple, but clean, mechanism
XT:for both externalized and internally held
XT:help information. It was written only for
XT:fun, but may prove useful in standardized
XT:help utilities as its' features are tuned
XT:up and refined.  Any comments from anyone
XT:out there? Or is this idea just too wierd
XT:and far-fetched.
X
X/* lower level menu that is all text */
X#:4
XX:30
XY:14
XT:This is all Text, so you
XT:can't really do much but
XT:look at it and then push
XT:the left arrow key.     
X
X/* small menu */
X#:6
XX:50
XY:3
XT:Menu 6
X+:GOTO 5
X=:5
X+:GOTO 1
X=:1
X
X/* menu that is really a file */
X#:10
XX:3
XY:5
X<:sample.txt
X
X/* just a test to show what a missing file will do */
X#:11
XX:3
XY:5
X<:hl.txt
X
X/* another little text menu */
X#:5
XX:70
XY:20
XT:JUST
XT:MORE
XT:Text
SHAR_EOF
chmod 0600 MENU.TRB || echo "restore of MENU.TRB fails"
sed 's/^X//' << 'SHAR_EOF' > README.TRB &&
X/* This isn't meant to be read THIS way! Run README.PRG and check it out.    */
X/* This file MUST be in the same directory as README.PRG for README to run.  */
X/* Since you are looking at this file, note that this is the file that makes */
X/* up the beginning display when you first invoke README.PRG. By replacing   */
X/* This page with your own, and making your own MENU.TRB file, you will have */
X/* your own customized standalone help reader */
X
X                            POPUP HELP MENU DEMO
X                               by Todd Burkey
X
X  Hate clicking on and paging through README files?  Well, give this program a
X  try. README.PRG is a standalone program that uses my POPUP HELP mechanism to
X  create nice, heirarchical help menus. Originally intended for HDSCAN, I have
X  decided to release this README application w/source code so others out there
X  can use it, learn from it, and hopefully even improve on it. POPHELP is easy
X  to use, just press HELP and use the arrows to move around.  Press HELP again
X  (while inside POPHELP) if you get confused.  Yep, even mono-chrome and mouse
X  lovers are supported. Some technical notes:
X
X    1) POPHELP is file driven. A procedure reads in MENU.TRB which describes
X       the popup hierarchy. Think of this as a help resource file.
X    2) POPHELP has a limit of 100 popup menus (as compiled herein). Menu 0 is
X       for people who get confused.
X    3) Short (<24 line) files can be automatically shown (see the examples.)
SHAR_EOF
chmod 0600 README.TRB || echo "restore of README.TRB fails"
sed 's/^X//' << 'SHAR_EOF' > SAMPLE.TXT &&
X/* SAMPLE Two level Tree */
X#:1
XX:5
XY:15
XT:WELCOME TO POPHELP
X+:Some Error Testing
X=:42
X
X#:42
XX:10
XY:6
XT:LEVEL TWO MENU
X+:Goto menu 1    
X=:1
X+:Menu Doesn't exist
X=:88
SHAR_EOF
chmod 0600 SAMPLE.TXT || echo "restore of SAMPLE.TXT fails"
exit 0