/*========================================================*
*=========================================================*
*
*
*  Listing 1:
*
*
*           Main.c
*           Read an input file and construct the menu.
*
*           This code MAY NOT be redistributed if it is
*           modified in any manner whatsoever.
*
*
*           (For Lattice/Sas Version 5.10a or higher) 
*
*           Compile:  lc -cfist -v -y -b1 main.c
*
*           Link:  Blink FROM
*                  c.o
*                  main.o
*                  a_source.o
*                  b_source.o
*                  c_source.o
*
*                  TO ms
*                  LIB
*                  lc.lib
*
*                 
*     MenuScript Version 1.14 (2 December 1991)
*     Copyright (c) 1991 David T. Ossorio.
*     All Rights Reserved.    
*
*=========================================================*
*========================================================*/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/diskfont.h>
#include <graphics/text.h>
#include <graphics/gfxbase.h>
#include <intuition/intuition.h>

#ifdef LATTICE
#include <proto/all.h>
#endif

#define VERSION 1
#define REVISION 14

#ifndef ABS                       
#define ABS(x) (x)<0?-(x):(x)
#endif

/* Here are all of the default states for the switches */

#define DEFAULT_STATE_D TRUE    /* Do display the menu */
#define DEFAULT_STATE_D_STR "OFF"

#define DEFAULT_STATE_P TRUE    /* Do print the menu */
#define DEFAULT_STATE_P_STR "OFF"

#define DEFAULT_STATE_L TRUE    /* Do show line numbers */
#define DEFAULT_STATE_L_STR "OFF"

#define DEFAULT_STATE_C TRUE  /* Do print c source code */
#define DEFAULT_STATE_C_STR "ON"

#define DEFAULT_STATE_A FALSE  /* Don't print 
                                  assembler source code */
#define DEFAULT_STATE_A_STR "OFF"

#define DEFAULT_STATE_B FALSE
#define DEFAULT_STATE_B_STR "OFF"


/*========================================================
*     Window defaults
*=======================================================*/


#define DEFAULT_WINDOW_WIDTH        640
#define DEFAULT_WINDOW_HEIGHT       200
#define DEFAULT_WINDOW_DEPTH        2
#define DEFAULT_WINDOW_DETAIL_PEN   2
#define DEFAULT_WINDOW_BLOCK_PEN    1
#define DEFAULT_WINDOW_FLAGS        WINDOWCLOSE|ACTIVATE\
                               |NOCAREREFRESH|WINDOWDEPTH
                                    
#define DEFAULT_WINDOW_IDCMP      CLOSEWINDOW
#define DEFAULT_WINDOW_TITLE      "MenuScript Version 1.14"

/*========================================================
*  IntuiText defaults
*=======================================================*/

#define DEFAULT_IT_FP   2 /* frontpen */
#define DEFAULT_IT_BP   1 /* backpen */
#define DEFAULT_IT_LE   2 /* leftedge */
#define DEFAULT_IT_TE   1 /* topedge */
#define DEFAULT_IT_MD   JAM2 /* drawmode */
#define DEFAULT_IT_MD_STR "JAM2" /* for display */
         
/*========================================================
* Menu Defaults
*=======================================================*/


#define DEFAULT_MENU_NAME "MText"   /* variable name */
#define DEFAULT_MENU_FLAGS MENUENABLED /* assume enabled */
#define DEFAULT_MENU_FLAGS_STR "MENUENABLED" 
                              /* for display purposes */
                              
#define DEFAULT_ITEM_FLAGS ITEMTEXT|ITEMENABLED|HIGHCOMP
#define DEFAULT_ITEM_FLAGS_STR "ITEMTEXT|"\
"ITEMENABLED|HIGHCOMP"
                               
#define STARTING_LEFTEDGE 2   /* initial leftedge */
#define DEFAULT_OFFSET 75    /* overlap of subitems */
#define DEFAULT_ITEMEDGE 0    /* left edge of items */

/*========================================================
* Macros
*=======================================================*/

#define MEMF_FLAGS MEMF_PUBLIC|MEMF_CLEAR /* default 
                                          memory flags */

/* 
   NEW(S) returns a pointer to a new object
   of type (struct s).  Used to create new
   menu and item sturctures, among other things */
                                             
#define NEW(s) ( (struct s *)AllocRemember\
       (&RememberKey,(ULONG)sizeof(struct s),MEMF_FLAGS))
#define NEWSTRING(s) ( (UBYTE *)AllocRemember\
                     (&RememberKey,(ULONG)(s),MEMF_FLAGS))

/* 
   A quick way to turn on or off a flag in a menu or
   item structure
*/
   

#define FLAG_OFF(Var,Flag) Var &= ~(Flag)
#define FLAG_ON(Var,Flag)  Var |=  (Flag)

/*========================================================
* Error Numbers
*=======================================================*/

#define ER_BREAK           -1 /* ctrl-c pressed */
#define ER_NO_ERRORS       0  /* All's peachy */
#define ER_NO_INTUITION    1  /* No intuition.library*/
#define ER_UK_SWITCH       2  /* Unknown switch */
#define ER_NO_INPUT        3  /* Can't open input file */
#define ER_INVALID_TOKEN   4  /* Token not recognized */
#define ER_NO_ARG          5  /* No argument found */
#define ER_NO_SCREEN       6  /* Can't open screen */
#define ER_NO_WINDOW       7  /* Can't open window */
#define ER_2_FONT          8  /* .FONT used twice */
#define ER_NO_GRAPHICS     9  /* No graphics.library */
#define ER_NO_DISKFONT     10 /* No diskfont.library */
#define ER_NO_FONT         11 /* Can't open font */
#define ER_NO_MEM          12 /* Out of memory */
#define ER_NO_MODE         13 /* Invalid DRAWMODE */
#define ER_ITEM            14 /* .item before .menu */
#define ER_SUBI            15 /* .subi before .item */
#define ER_NO_QUOTE        16 /* Missing quote */
#define ER_INVALID_ARG     17 /* invalid argument */
#define ER_INVALID_OFFSET  18 /* -100 <= offset <= 100 */
#define ER_INVALID_ITEMEDGE 19 /* .itemedge must be < 0 */
#define ER_MISSING_END     20 /* no "#" in checkmarkdata */
#define ER_STACK_OVERFLOW  21 /* when printing c source */



#define MAX_CHAR  256       /* Length of input 
                           buffer/max line length */
#define L_VERSION 33L       /* Library version  */

/* 
   We use the '*' to indicate the default argument,
   but in practice it could be a different character
   if we wanted...
*/
   
#define DEFAULT_ARG '*'    /* use the default argument */
#define MAX_IMAGE_SIZE 4096   /* normally we won't 
                                 exceed this */

/*
   We need a rememberkey, since all memory is
   allocated using AllocRemember()
*/
struct Remember *RememberKey;  
    
struct GfxBase *GfxBase = NULL;    
struct Library *DiskfontBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Menu *DisplayMenu = NULL; /* MAIN menu */
struct Menu *CurrentMenu = NULL; 
struct MenuItem *CurrentItem = NULL;
struct MenuItem *CurrentSubItem = NULL;
struct Image *CheckMarkImage   = NULL;
struct RastPort *textrp = NULL; /* for display FONT */
struct TextFont *font = NULL;   /* display FONT */
struct TextAttr *textAttr = NULL; /* for display FONT */

UBYTE *cline = NULL;

   /* the input buffer is copied to dline
      in case it has to be displayed in an
      error message
   */
      
UBYTE *dline = NULL;
UBYTE *mname = NULL;
FILE *input = NULL;

/*
   All of these variables are set to resonable
   defaults; most are self-explanitory
*/


USHORT leftedge      = STARTING_LEFTEDGE;
SHORT offset         = DEFAULT_OFFSET;
SHORT itemedge       = DEFAULT_ITEMEDGE;
SHORT ww_width       = DEFAULT_WINDOW_WIDTH;
SHORT ww_height      = DEFAULT_WINDOW_HEIGHT;
SHORT ww_depth       = DEFAULT_WINDOW_DEPTH;
UBYTE ww_detail      = DEFAULT_WINDOW_DETAIL_PEN;
UBYTE ww_block       = DEFAULT_WINDOW_BLOCK_PEN;
ULONG ww_idcmp       = DEFAULT_WINDOW_IDCMP;
ULONG ww_flags       = DEFAULT_WINDOW_FLAGS;

UBYTE it_md          = DEFAULT_IT_MD; /* itext drawmode */
UBYTE it_fp          = DEFAULT_IT_FP; /* itext frontpen */
UBYTE it_bp          = DEFAULT_IT_BP; /* itext backpen */
SHORT it_te          = DEFAULT_IT_TE; /* itext topedge */
SHORT it_le          = DEFAULT_IT_LE; /* itext leftedge */

ULONG line_number    = 0; /* starting line number */

ULONG version = VERSION;
ULONG revision = REVISION;

/*
   Normally we don't use our own font
*/
   
BOOL own_font = FALSE; 

/*
   Text for the error messages
*/

UBYTE *error[] = {
   "No Errors.",
   "Can't open intuition.library.",
   "Unknown command switch.",
   "Can't open input file.",
   "Unknown command.",
   "Missing command parameter.",
   "Unable to open screen.",
   "Unable to open window.",
   ".FONT command only allowed once.",
   "Can't open graphics.library.",
   "Can't open diskfont.library.",
   "Unable to load requested font.",
   "Out of memory.",
   "Unknown DrawMode.",
   "Item before Menu.",
   ".SUBI before .ITEM or .MENU.",
   "Missing quote.",
   "Unknown .ITEM or .SUBI parameter.",
   "Offset must be between -100 and 100.",
   "Itemedge must be < 0.",
   "Possible missing '#' in image data.",
   "Stack overflow."
};


/*========================================================
*
* Function Prototypes
*
*=======================================================*/

extern VOID print_b_source(struct Menu *fm);
extern VOID print_a_source(struct Menu *fm);
extern VOID print_c_source(struct Menu *fn);

UBYTE *ReadCheckData(UBYTE *line);
VOID DisplaySettings(VOID);
VOID ProcessCheckMark(VOID);
VOID PrintHelp(VOID);
VOID Display(VOID);
BOOL tcmp(UBYTE *string,UBYTE *tkn);
VOID CleanExit
   (LONG error_numeber,BOOL display,ULONG return_value);
VOID ProcessMenu(VOID);
VOID ProcessItem(VOID),ProcessSubItem(VOID);
struct IntuiText *MakeIText(UBYTE *text);
VOID ProcessFont(VOID);
VOID ProcessItemArgs(struct MenuItem *item);
UBYTE *GetName(VOID);
VOID ProcessExclude(struct MenuItem *item);

USHORT MaxLength
(struct RastPort *txtrp,struct MenuItem *fi, USHORT width);
VOID AdjustText
(struct MenuItem *item,struct TextAttr *attr);
VOID AdjustSubItems
(struct RastPort *txtrp, struct MenuItem *fi,
 struct TextAttr *atr, USHORT wdth,USHORT hght,USHORT lvl,
 USHORT edge);
VOID AdjustWidths(struct Menu *FirstMenu);
VOID AdjustItems
   (struct RastPort *txtrp, struct MenuItem *fi, 
   struct TextAttr *atr,USHORT wdth,USHORT hght,
   USHORT lvl,USHORT edge);
VOID AdjustMenus
   (struct Menu *firstmenu, struct TextAttr *attr);               

/*
   We can exit gracefully with <ctrl-c> if
   using LATTICE...
*/   

#ifdef LATTICE
int CXBRK(void) 
{ CleanExit(ER_BREAK,FALSE,RETURN_OK); return (0); }
#endif


/*========================================================
*
*     main()
*
*=======================================================*/


void main(int argc, char *argv[])
{
   BOOL do_display = DEFAULT_STATE_D; /* Complete Menu ? */
   BOOL do_lines = DEFAULT_STATE_L;   /* Line Numbers ?  */
   BOOL do_write = DEFAULT_STATE_P;   /* Print source ?  */
   BOOL do_c_source = DEFAULT_STATE_C;/* Print C source? */
   BOOL do_asm_source = DEFAULT_STATE_B; /* Asm source ? */
   BOOL do_bas_source = DEFAULT_STATE_A;/* Basic source ?*/
   
   ULONG command; 
   REGISTER UBYTE *token = NULL;      
   REGISTER UBYTE *arg   = NULL; /* argument for tokens */
    
   if(argc < 2 || *(argv[1])=='?') 
      PrintHelp(); /* and exit */
    
/*
   Print greeting message.  Since output is 
   usually redirected,
   any output that should appear on the screen
   must be channeled through stderr...
*/
    
   fprintf
   (stderr,"\nMenuScript Version %d.%d\n",VERSION,REVISION);
   fprintf
   (stderr,"Copyright (c) 1991 David T. Ossorio.\n");
   fprintf
   (stderr,"All Rights Reserved.\n\n");
   
   /* open libraries */
   
   if(! (IntuitionBase = (struct IntuitionBase *)
      OpenLibrary("intuition.library",L_VERSION)) )
      CleanExit(ER_NO_INTUITION,FALSE,RETURN_WARN);
      
   if(! (GfxBase = (struct GfxBase *)
      OpenLibrary("graphics.library",L_VERSION)) )
      CleanExit(ER_NO_GRAPHICS,FALSE,RETURN_WARN);


   /* get memory for the input buffers    */
   
   if(!(cline = NEWSTRING(MAX_CHAR))) 
      CleanExit(ER_NO_MEM,FALSE,RETURN_WARN);
   if(!(dline = NEWSTRING(MAX_CHAR))) 
      CleanExit(ER_NO_MEM,FALSE,RETURN_WARN);
         
   /*    open up our default font   */
   /*    this SHOULD always open... */
   
   if(!(textAttr = NEW(TextAttr))) 
      CleanExit(ER_NO_MEM,FALSE,RETURN_WARN);
   if(!(textrp   = NEW(RastPort))) 
      CleanExit(ER_NO_MEM,FALSE,RETURN_WARN);
   
   /* We always use the topaz 80 font 
      if the user dosen't specify otherwise.
      (Although if topaz 80 is used, 
      we DO NOT print the textAttr structure).
   */   
   
   /* Initialize */
   textAttr->ta_Name    = (STRPTR)"topaz.font";
   textAttr->ta_YSize   = TOPAZ_EIGHTY;
   textAttr->ta_Style   = FS_NORMAL;
   textAttr->ta_Flags   = FPF_ROMFONT;
   
   if(!(font = (struct TextFont *)OpenFont(textAttr)) )
      CleanExit(ER_NO_FONT,FALSE,RETURN_WARN);
      
   SetFont(textrp,font);
      
/*========================================================
* Process command line flags
*=======================================================*/

   while (--argc > 0 && (*++argv)[0] == '-')
      while (command = *++argv[0])
         switch(tolower(command)) {
            case 'd':
               do_display     = FALSE;
               break;
            case 'p':
               do_write       = FALSE;
               break;
            case 'l':
               do_lines       = FALSE;
               break;
            case 'c':
               do_c_source    = TRUE;
               do_asm_source  = FALSE;
               do_bas_source  = FALSE;
               break;
            case 'a':
               do_asm_source  = TRUE; 
               do_c_source    = FALSE;
               do_bas_source  = FALSE;  
               break;
            case 'b':
               do_bas_source  = TRUE;
               do_asm_source  = FALSE;
               do_c_source    = FALSE;
               break;
            case 'z':
               DisplaySettings();
               break;   
           default:
               fprintf(stderr,"-%c \n",*argv[0]);
               CleanExit(ER_UK_SWITCH,FALSE,RETURN_WARN);
               break;
               }        /* end switch */                 


      /* open the input file */
      
      if(!(input = fopen(*argv,"r")) )
         CleanExit(ER_NO_INPUT,FALSE,RETURN_WARN);
         
      fprintf(stderr,"Reading...");
      
/*=========================================================
*
* Process the input file
*
*========================================================*/

/*
   Continue to read lines until we
   reach the end of the file.  Each
   line contains a single statement.
*/

   while ( fgets(cline,MAX_CHAR,input) ) {           
      if(do_lines) 
         fprintf(stderr,"%6u\b\b\b\b\b\b",line_number++);
   
         
/*---------------- process the line ---------------------*/
      
      token = strtok(cline,"\x20\n\t\f\v\r");/* 1st token*/
      
      /* skip comments */
      
      if ( *token == '*' || *token == ';' 
            || !isgraph(*token) ) continue;
      
      /*    
            We may need to print this line later 
            in an error message.
            Since strtok() corrupts it,
            we copy the line to a safe place.
      */
      
      strcpy(dline,cline);
      
   /*
      Note that for speed, tokens that are most likely
      to be encountered (i.e, .MENU,.ITEM,.SUBITEM) are 
      checked for FIRST.  This way we don't spend 
      a lot of time executing 'if' statements.
   */
   
   
   /*=====================================================
   *
   *     Here is a list of valid first tokens:
   *
   *     .menu               -- menu with this name
   *     .item               -- item
   *     .subi               -- subitem
   *     .width              -- sets window width 
   *                            (should be 640 or 320)
   *     .height             -- sets window height 
   *                            (200 or 400)
   *     .name               -- sets name of menu 
   *                            (for SetMenuStrip())
   *     .depth              -- set window depth
   *     .w_detail           -- set detail_pen of window
   *     .w_block            -- set block_pen of window
   *     .font               -- use your own
   *     .mode               -- draw mode 
   *                            (JAM1,etc for menu items )
   *     .a_source           -- same as -a switch
   *     .b_source           -- same as -b switch
   *     .c_source           -- same as -c switch
   *     .itemedge           -- leftedge of menuitem strips
   *     .offset             -- offset of subitem boxes
   *     .it_frontpen        -- set frontpen of intuitext
   *     .it_backpen         -- set backpen of intuitext
   *     .it_leftedge        -- set leftedge of intuitext
   *     .it_topedge         -- set topedge of intuitext
   *     .checkimage         -- custom checkmark image
   *     
   *=====================================================*/     

      if (tcmp(token,".menu")) {          /* .MENU */
         ProcessMenu();
         continue;
      }
   
      if (tcmp(token,".item")) {          /* .ITEM */
         ProcessItem();
         continue;
      }
   
      if (tcmp(token,".subi")) {          /* .SUBI */
         ProcessSubItem();
         continue;
      }
   
      if (tcmp(token,".font")) {          /* .FONT */
         ProcessFont();
         own_font = TRUE;
         continue;
      }

      if (tcmp(token,".checkimage")) { /* .CHECKIMAGE */
         ProcessCheckMark();
         continue;
      }
        
      if  (tcmp(token,".c_source")) { /* C.SOURCE */
         do_c_source = TRUE;
         do_asm_source = do_bas_source = FALSE;
         continue;
      }
    
      if  (tcmp(token,".a_source")) { /* A.SOURCE */
         do_asm_source = TRUE;
         do_c_source = do_bas_source = FALSE;
         continue;
      }
   
 
      if (tcmp(token,".b_source")) { /* B.SOURCE */
         do_bas_source = TRUE;
         do_c_source = do_asm_source = FALSE;
         continue;
      }
   
      if (tcmp(token,".name")) {       /* .NAME */
         mname = GetName();   
         continue;
      }

      if (tcmp(token,".mode")) { /* .MODE */
         arg = strtok(NULL,"\x20\t\n\f\v\r");
         if(*arg == DEFAULT_ARG) it_md = DEFAULT_IT_MD;
         else {
            if(tcmp(arg,"jam1")) it_md = JAM1; 
            else if(tcmp(arg,"jam2")) it_md = JAM2; 
            else if(tcmp(arg,"complement")) 
                  it_md = COMPLEMENT; 
            else if(tcmp(arg,"inversvid"))  
                  it_md |= INVERSVID; 
               
            else CleanExit(ER_NO_MODE,TRUE,RETURN_WARN);
         }
       continue;
      }
  
   /* 
      Get the command parameter 
      (usually this will be a number)
      We always check for the '*' character
      as a parameter.  If found, then
      we set the default.
   */  
  
      arg = strtok(NULL,"\x20\t\n\v\f\r"); /* grab param */                               
      
      if(!isgraph(*arg)) 
         CleanExit(ER_NO_ARG,TRUE,RETURN_WARN);
   
      if       (tcmp(token,".width"))        /* .WIDTH */
         if(*arg == DEFAULT_ARG) 
            ww_width = DEFAULT_WINDOW_WIDTH;
         else ww_width = atoi(arg);
             
      else if  (tcmp(token,".height"))       /* .HEIGHT */
         if(*arg == DEFAULT_ARG) 
            ww_height = DEFAULT_WINDOW_HEIGHT;
         else ww_height = atoi(arg);
         
      else if  (tcmp(token,".depth"))        /* .DEPTH */           
         if(*arg == DEFAULT_ARG) 
            ww_depth = DEFAULT_WINDOW_DEPTH;
         else ww_depth = atoi(arg);
         
      else if  (tcmp(token,".w_detail"))   /*.W_DETAIL */       
         if(*arg == DEFAULT_ARG) 
            ww_detail = DEFAULT_WINDOW_DETAIL_PEN;
         else ww_detail = atoi(arg);
         
      else if  (tcmp(token,".w_block"))    /*.W_BLOCK */
         if(*arg == DEFAULT_ARG) 
            ww_block = DEFAULT_WINDOW_BLOCK_PEN;
         else ww_block = atoi(arg);
         
      else if(tcmp(token,".it_frontpen")) /*.IT_FRONTPEN */
         if(*arg == DEFAULT_ARG) 
            it_fp = DEFAULT_IT_FP;
         else it_fp = atoi(arg);
         
      else if(tcmp(token,".it_backpen")) /*.IT_BACKPEN */
         if(*arg == DEFAULT_ARG) 
            it_bp = DEFAULT_IT_BP;
         else it_bp = atoi(arg);
         
      else if(tcmp(token,".it_leftedge")) /*.IT_LEFTEDGE */
         if(*arg == DEFAULT_ARG) 
            it_le = DEFAULT_IT_LE;
         else it_le = atoi(arg);
         
      else if(tcmp(token,".it_topedge")) /*.IT_TOPEDGE */  
         if(*arg == DEFAULT_ARG) 
            it_te = DEFAULT_IT_TE;
         else it_te = atoi(arg);
     
      else if  (tcmp(token,".itemedge")) { /*.ITEMEDGE */
         if(*arg == DEFAULT_ARG) 
            itemedge = DEFAULT_ITEMEDGE;
         else {       
               itemedge    = atoi(arg);
               if(itemedge > 0) /* Can't be > 0 */
                  CleanExit
                    (ER_INVALID_ITEMEDGE,TRUE,RETURN_WARN);
               }
      }
     
      else if  (tcmp(token,".offset")) { /* .OFFSET */
         if(*arg == DEFAULT_ARG) 
            offset = DEFAULT_OFFSET;
         else {
               offset      = atoi(arg);
               if (offset < -100 || offset > 100)
                  CleanExit
                    (ER_INVALID_OFFSET,TRUE,RETURN_WARN);
               }
      }
      
  
      else CleanExit(ER_INVALID_TOKEN,TRUE,RETURN_WARN);
        
         
   }  /* end while (main loop) */      
 
       
   /* Now fill in all of the positioning information */
      
   AdjustMenus(DisplayMenu,textAttr);

   if(!mname) mname = (UBYTE *)DEFAULT_MENU_NAME;
      
   if(do_display) Display(); /* Show the completed menu */
   
   if(do_write) { /* Skip if the user wants no source */
      
      if(do_bas_source) print_b_source(DisplayMenu);
      if(do_c_source)   print_c_source(DisplayMenu);
      if(do_asm_source)   print_a_source(DisplayMenu);
   }
                
   /*   All done!!! */         
                
   CleanExit(ER_NO_ERRORS,FALSE,RETURN_OK); /* BYE !!! */
      
}        /*** END MAIN ***/  


/*========================================================
*
*        display()
*
*
*  Display the completed menu EXACTLY as it will be
*  described in the output source code.
*
*
*=======================================================*/


VOID Display(VOID)
{
   struct Window *Display_Window = NULL;
   struct Screen *Display_Screen = NULL;
   REGISTER struct NewWindow *nw = NEW(NewWindow);
   REGISTER struct NewScreen *ns = NEW(NewScreen);
   
   if(!nw || !ns) CleanExit(ER_NO_MEM,FALSE,RETURN_WARN);
   
   /*
      After the NewWindow structure has been
      allocated dynamically, fill in all of
      the parameters for the display window
   */
   
   ns->Width      = nw->Width    = ww_width;
   ns->Height     = nw->Height   = ww_height;
   ns->Depth      = ww_depth;
   ns->DetailPen  = ww_detail;
   ns->BlockPen   = ww_block;
   nw->Type = ns->Type           = CUSTOMSCREEN;
   nw->DetailPen  = nw->BlockPen = -1;
   nw->Flags      = ww_flags;
   nw->IDCMPFlags = ww_idcmp;
   nw->Title      = (UBYTE *)DEFAULT_WINDOW_TITLE; 
   
   if(ww_width >  320) FLAG_ON(ns->ViewModes,HIRES);
   if(ww_height > 200) FLAG_ON(ns->ViewModes,LACE);

   if(CheckMarkImage) nw->CheckMark = CheckMarkImage;
   
   ns->Font = textAttr;
   
   /* Open the screen */

   if(!(nw->Screen = Display_Screen = (struct Screen *)
      OpenScreen(ns)) )
      CleanExit(ER_NO_SCREEN,FALSE,RETURN_WARN);
      
   /* Open the window */
      
   if(!(Display_Window = (struct Window *)
      OpenWindow(nw)) ) 
      CleanExit(ER_NO_WINDOW,FALSE,RETURN_WARN);    

   /* Display directions */
   
   Move(Display_Window->RPort,10,30);
   SetAPen(Display_Window->RPort,1);
   Text(Display_Window->RPort,
      "Close window to print source code.",
   strlen("Close window to print source code."));
   
   /* Display the menu and wait
      for the user to close the window 
    */

   if(DisplayMenu) 
      SetMenuStrip(Display_Window,DisplayMenu);
   Wait(1L<<Display_Window->UserPort->mp_SigBit);
   if(DisplayMenu) 
      ClearMenuStrip(Display_Window);
   
   /* Cleanup */
   
   CloseWindow(Display_Window);
   CloseScreen(Display_Screen);

}     /*** END DISPLAY ***/


/*========================================================
*
*   getname()
*
*  Grabs the text inbetween quotes.(either " \" " or " ' "
*  can be used as quote characters).
*
*
*=======================================================*/

UBYTE *GetName(VOID)
{
   UBYTE *return_name = NULL;
   REGISTER UBYTE *name = strtok(NULL,"\"'");
   
   if(!name)
      CleanExit(ER_NO_QUOTE,TRUE,RETURN_WARN);
      
   name = strtok(NULL,"\"'");
   if(!name)
      CleanExit(ER_NO_QUOTE,TRUE,RETURN_WARN);
      
   if(! (return_name = NEWSTRING(strlen(name))) )
      CleanExit(ER_NO_MEM,FALSE,RETURN_WARN);

   strtok(NULL,",\t\n ");
   
   strcpy(return_name,name);
   return(return_name);

}  /*** END GetName ***/             


/*========================================================
*
*           tcmp()
*
*  Simplifies comparison of tokens.  MUCH easier to
*  use than the idiotic strcmp().
*
*  Also converts everything to lower case, so commands
*  and parameters are case-insensitive.
*
* Returns TRUE if a match is found, else returns FALSE
*
*=======================================================*/

BOOL tcmp(token,string)
UBYTE *token;
UBYTE *string;
{  
   REGISTER ULONG i = 0;
   REGISTER UBYTE *tkn = token;
   REGISTER UBYTE *str = string;
   
   /* convert to lower case */
   
   while ( isgraph(tkn[i] = tolower(tkn[i])) ) 
   i++;
   
   if (! (strncmp(tkn,str,i)) ) return TRUE;
   else return FALSE;

}  /*** END tcmp ***/


/*========================================================
*
*        ProcessMenu()
*
*  Adds a new menu.
*  When a '.menu' command is encountered, it
*  is this routine which links the new menu to
*  the existing menu strip.
*
*=======================================================*/

VOID ProcessMenu(VOID)
{
   REGISTER struct Menu *ThisMenu = NEW(Menu);
   UBYTE *token;
   
   CurrentItem = NULL;     /* start new menu */
   
   if(!ThisMenu) CleanExit(ER_NO_MEM,FALSE,RETURN_WARN);
   ThisMenu->Flags      = DEFAULT_MENU_FLAGS;
   ThisMenu->MenuName   = GetName();
   

     
   /*       check for arguments after menu name       */
   
   token = strtok(NULL,"\x20,\t\n\v\r\n");
   
   if(isgraph(*token)) {
      if(tcmp(token,".off")) 
         FLAG_OFF(ThisMenu->Flags,MENUENABLED);
      else if(*token != ';' && *token != '*') 
          CleanExit(ER_INVALID_TOKEN,TRUE,RETURN_WARN);
   }
   
   if(!DisplayMenu) /* First item on the list */
      DisplayMenu = CurrentMenu = ThisMenu; 
   
   else {
      CurrentMenu->NextMenu = ThisMenu;   
      CurrentMenu = ThisMenu;/* LINK to the previous menu */
   }
   
   return;

}     /*** END ProcessMenu ***/
   
              

/*=======================================================
*
*        ProcessItem()
*
*  
*  Adds a new item to the most recent .MENU
*  When an '.item' command is encountered, it
*  is this routine which links a new item to
*  the current item box for the current menu.
*
*======================================================*/

VOID ProcessItem(VOID)
{
   REGISTER struct MenuItem *ThisItem = NEW(MenuItem);

   CurrentSubItem = NULL;     /* start new item */
   
   if(!ThisItem) CleanExit(ER_NO_MEM,FALSE,RETURN_WARN);
   
   ThisItem->LeftEdge   = itemedge; 
   ThisItem->Flags      = DEFAULT_ITEM_FLAGS;
   ThisItem->ItemFill   = (APTR)MakeIText(GetName());       
  
   ProcessItemArgs(ThisItem);

   if(!CurrentItem)        /* first item for CurrentMenu */
      CurrentMenu->FirstItem = CurrentItem = ThisItem;
            
   else {
      CurrentItem->NextItem = ThisItem; 
      CurrentItem = ThisItem; /* link to previous item */
   }

   return;

}     /*** END ProcessItem() ***/


/*========================================================
*
*           ProcessItemArgs()
*
*  This routine is called from ProcessItem() or
*  ProcessSubItem().  It reads all arguments after
*  an '.item' or '.subitem' command and sets the
*  appropriate MenuItem->Flags.
*
*  Current valid parameters for .item or .subi:
*
*  key x     -- set command key equivalent 'x'
*  checkable -- able for this item to be checked
*  check     -- set initial check for a .checkable item
*  off       -- this item initially unavailable
*  exclude   -- this item excludes all items in the list
*               (items are numbered starting from 1)
*  toggle    -- toggle for checkmark. 
*  box       -- select box highlighting
*  none      -- select no highlighting
*  comp      -- select complement highlighting (default)
*  select <name>   -- <name> appears when selected   
*
*=======================================================*/

VOID ProcessItemArgs(item)
struct MenuItem *item;
{
   REGISTER UBYTE *arg;
   REGISTER UBYTE *arg1;
      
   do  {
      
      arg = strtok(NULL,"\x20\n,\t\v\f\r");/* 1st token */
      
      /* if we see a comment character, we're done */
      
      if (*arg == ';' || *arg == '*' || !isgraph(*arg)) 
         break;
      
      if (tcmp(arg,"check")) {         /* CHECK */
         FLAG_ON(item->Flags,CHECKED);
         continue;
      }
      
      if (tcmp(arg,"key")) {           /* KEY */
         
         arg1 = strtok(NULL,"\x20,\t\n\v\f\r");
         if(!isgraph(*arg1)) 
            CleanExit(ER_NO_ARG,TRUE,RETURN_WARN);   
         
         FLAG_ON(item->Flags,COMMSEQ);
         item->Command = *arg1;
         continue;
      }
      
      if(tcmp(arg,"checkable")) {   /* CHECKABLE */
         FLAG_ON(item->Flags,CHECKIT);
         continue;
      }
      
      
      if(tcmp(arg,"off"))  {        /* OFF */
            FLAG_OFF(item->Flags,ITEMENABLED);
            continue;
      }
             
      if(tcmp(arg,"toggle"))  {     /* TOGGLE */
            FLAG_ON(item->Flags,MENUTOGGLE); 
            continue;
      }
     
      if(tcmp(arg,"box")) {          /* BOX */
          FLAG_OFF(item->Flags,HIGHNONE|HIGHCOMP|HIGHIMAGE);
          FLAG_ON(item->Flags,HIGHBOX);
          continue;
      }
                 
      if(tcmp(arg,"comp")) {         /* COMP */
         FLAG_OFF(item->Flags,HIGHNONE|HIGHIMAGE|HIGHBOX);
         FLAG_ON(item->Flags,HIGHCOMP);
         continue;
      }
      
      if(tcmp(arg,"none")) {      /* NONE */
         FLAG_OFF(item->Flags,HIGHCOMP|HIGHIMAGE|HIGHBOX);
         FLAG_ON(item->Flags,HIGHNONE);
         continue;
      }
      
      
      if(tcmp(arg,"exclude")) {   /* EXCLUDE */
         ProcessExclude(item);
         continue;
      }  
             
      if(tcmp(arg,"select")) {    /* SELECT */
         FLAG_OFF(item->Flags,HIGHBOX|HIGHCOMP|HIGHNONE);
         FLAG_ON(item->Flags,HIGHIMAGE);
         item->SelectFill = (APTR)MakeIText(GetName());
         continue;
              
      }
                
      CleanExit(ER_INVALID_ARG,TRUE,RETURN_WARN);
                 
     
      
   } while (TRUE);    /*    end do loop   */
   
   return;

}  /*** END ProcessItemArgs() ***/

/*=========================================================
* PrintHelp()
* if the user types 'ms' without arguments or 'ms ?',
* the following is displayed:
*========================================================*/

VOID PrintHelp()
{
   printf
   ("\nMenuScript Version %d.%d Usage:\n\n",VERSION,REVISION);
   printf
   ("\tms [>redirection file] [-[dplcabz]] inputfile\n\n");
   printf
   ("\tWhere:\n");
   printf
   ("\t\t[>redirection file]"
      " is where you want the output to go.\n");
   printf
   ("\t\tFlags:\n");
   printf
   ("\t\td :  DO NOT display the menu.\n");
   printf
   ("\t\tp :  DO NOT write the source "
      "code for the menu.\n");
   printf
   ("\t\tl :  DO NOT display line numbers "
           "when reading the input file.\n");
   printf
   ("\t\tc :  write C source code (default).\n");
   printf
   ("\t\ta :  write Assembler source code.\n");
   printf
   ("\t\tb :  write AmigaBasic source code.\n");
   printf
   ("\t\tz :  Display default settings.\n\n");
   printf
   ("\tNote: Command switches may be used in any order,\n");
   printf
   ("\tbut only one of: a,b,c may be used.\n\n");
      
   
   exit(RETURN_OK);
   

}  /*** END PrintHelp() ***/


/*========================================================
*
*        ProcessExclude()
*        Reads the list of numbers after the
*        'EXCLUDE' parameter and sets the appropriate
*        bits of item->MutualExclude
*
*=======================================================*/

VOID ProcessExclude(struct MenuItem *item)
{
   REGISTER UBYTE *argument;
   
   do {
      argument = strtok(NULL,"\x20,");
      if(!isdigit(*argument)) 
         break; /* read until no more digits */ 
      
      item->MutualExclude |= 1L << (ULONG)(atoi(argument));
      
      } while (TRUE);
   return;

}  /*** END ProcessExclude() ***/
    
/*========================================================
/*
*
*  ProcessSubItem()
*  This routine is simialir to ProcessItem()
*  When a '.subi' command is found, it links it
*  to the current list of subitems for the current
*  item.
*
*=======================================================*/

VOID ProcessSubItem(VOID)
{
   REGISTER struct MenuItem *ThisSubItem = NEW(MenuItem);
   
   if(!ThisSubItem) CleanExit(ER_NO_MEM,FALSE,RETURN_WARN);
   ThisSubItem->Flags = DEFAULT_ITEM_FLAGS;
   ThisSubItem->ItemFill = (APTR)MakeIText(GetName());

/* 
   We hide the current offset in 
   ThisSubItem->LeftEdge, to be
   processed later by adjustmenus()
*/
   
   ThisSubItem->LeftEdge = offset;
      
   ProcessItemArgs(ThisSubItem);
   
   if(!CurrentSubItem)     /* first subitem for this item */
      CurrentItem->SubItem = CurrentSubItem = ThisSubItem;
      
   else {
      CurrentSubItem->NextItem   = ThisSubItem; 
      
               /* link to previous subitem */
      
      CurrentSubItem             = ThisSubItem;
   }    
   return;
   
}     /*** END ProcessSubItem() ***/ 

/*========================================================
*
*     MakeIText()
*
* Given a string as input, MakeIText()
* creates an IntuiText structure from that string.
*
*=======================================================*/

struct IntuiText *MakeIText(text)
UBYTE *text;
{
   REGISTER struct IntuiText *itext = NEW(IntuiText);
   
   if(!itext) CleanExit(ER_NO_MEM,FALSE,RETURN_WARN);
   
   itext->FrontPen  = it_fp;  /* set all of these with */
   itext->BackPen   = it_bp;  /* their current values */  
   itext->DrawMode  = it_md;
   itext->LeftEdge  = it_le;
   itext->TopEdge   = it_te;
   itext->IText     = text;
   
   return(itext);
   
}     /*** END MakeIText() ***/

/*========================================================
*
*        ProcessFont()
* This routine is called to when a '.FONT' command
* is encountered.
*
*========================================================*/

VOID ProcessFont(VOID)
{
   UBYTE *name = GetName(); /* grab the name of the font */
   UBYTE *size = strtok(NULL,",\t\n "); /* grab the size */

      
   if(!isgraph(*size)) 
      CleanExit(ER_NO_ARG,TRUE,RETURN_WARN);
   if(own_font)   /* if this is TRUE, we've done this 
                    before... */ 

      CleanExit(ER_2_FONT,TRUE,RETURN_WARN);
   
   else 
      own_font = TRUE;

   CloseFont(font);     /* close old font */
   
   textAttr->ta_Name    = name;     /* initialize */
   textAttr->ta_YSize   = atoi(size);
   textAttr->ta_Style   = FS_NORMAL;
   textAttr->ta_Flags   = FPF_ROMFONT;
   
  
   /*    try a ROM-based font first  */
   
   if( (font = (struct TextFont *)OpenFont(textAttr)) ) 
      ;        /* fine, skip the disk stuff */
   
   /*    try a diskfont before we give up */
   
   else {
      if(! (DiskfontBase = (struct Library *)
         OpenLibrary("diskfont.library",L_VERSION)) )
            CleanExit(ER_NO_DISKFONT,FALSE,RETURN_WARN);
            
      textAttr->ta_Flags = FPF_DISKFONT;
      
      if(!(font=(struct TextFont *)OpenDiskFont(textAttr)))
         CleanExit(ER_NO_FONT,TRUE,RETURN_WARN);
     }      
   
   SetFont(textrp,font);
   return;

}     /*** END ProcessFont() ***/

/*========================================================
*
*        cleanexit()
*
*  Do a through job of cleaning up after ourselves,
*  and gracefully exit...
*  Also display an error message and line if necessary.
*
*======================================================*/

VOID CleanExit(Error_Number,Display_Line,ReturnValue)
LONG Error_Number;
BOOL Display_Line;
ULONG ReturnValue;
{
   
   /*    Clean up and exit    */
   
   
   if(Error_Number == ER_BREAK) {
      DisplayBeep(NULL);
      fprintf
      (stderr,"\n***BREAK:  MenuScript terminating.\n");
   }
   
   else if(Error_Number)  {
      if(Display_Line) fprintf
         (stderr,"\x20\x20\x20\x20\x20\x20"
         "\n%d:  %s\n",line_number,dline);
      fprintf(stderr,
     "ERROR: (%d) %s\n\n",Error_Number,error[Error_Number]);
   }
   
   else fprintf(stderr,"\n%s\n\n",error[Error_Number]);
   
  
   if(font)                CloseFont(font);
   
   FreeRemember(&RememberKey,TRUE);
   if(IntuitionBase)
      CloseLibrary((struct Library *)IntuitionBase);
   if(GfxBase)
      CloseLibrary((struct Library *)GfxBase);
   if(DiskfontBase)
      CloseLibrary((struct Library *)DiskfontBase);
   if(input)
      fclose(input);
  
   exit(ReturnValue);
   
}     /*** END CleanExit ***/

/*=========================================================
*
*           AdjustMenus()
*
*        sets Width,Height, fonts for menus and items.
*
*
*  These are  modified versions of the AdjustMenus() 
*  routines in the RKM pp. 131-132.
*
*
*========================================================*/

/*=======================================================
*  AdjustText()
*
*  Set up the ITextFont fields 
*  of the IText structs of menus...
*
*========================================================*/

VOID AdjustText(struct MenuItem *item, struct TextAttr *attr)
{
   REGISTER struct IntuiText *itemfill   = 
                   (struct IntuiText *)item->ItemFill;
   REGISTER struct IntuiText *selectfill = 
                   (struct IntuiText *)item->SelectFill;
   
   itemfill->ITextFont = attr;
   if(item->SelectFill) selectfill->ITextFont = attr;
   
   
}

/*=========================================================
*
*  AdjustSubItems()
*  Calculates TopEdge,Width, and Height for each subitem
*  in a subitem box.
*
*=========================================================*/

VOID AdjustSubItems(struct RastPort *txtrp, 
      struct MenuItem *fi,struct TextAttr *atr, 
      USHORT wdth, USHORT hght, USHORT lvl,
      USHORT edge)
{
   REGISTER struct MenuItem *subi = fi;
   REGISTER USHORT num = 0;
   USHORT strip_width;

   
   if (!subi) return;
   
  
   strip_width = MaxLength(txtrp,subi,wdth);
   
   while (subi) {
      
      subi->TopEdge = (num*hght)-lvl;
      subi->Width = strip_width;
      subi->Height = hght;
      AdjustText(subi,atr);
      subi = subi->NextItem;
      num++;
   }
   return;
} 


/*=======================================================
*
* MaxLength()
*
* MaxLenght() reads through each item in an item box and
* finds the item with the maximum text width.  Note that we
* need this routine because the item box is widend to 
* accomodate this widest item, so EACH item in the item
* box must have this maximum width.
*
* Items are also checked for the presence of a command
* key equivalent, and if found, are widend according to
* the screen width (LOWCOMMMWIDTH OR COMMWIDTH).
*
*=======================================================*/ 

USHORT MaxLength(struct RastPort *txtrp, 
   struct MenuItem *fi, USHORT width)
{
   REGISTER USHORT maxval = 0, textlen;
   struct MenuItem *item = fi;
   struct IntuiText *itext;
   
   
   while(item) {
      if(item->Flags&COMMSEQ) {
         width +=   
         (width+((ww_width<=320)?LOWCOMMWIDTH:COMMWIDTH));
         break;
      }
      item = item->NextItem;
   }
   item = fi;
   
   /* Find Max Width */
   
   while(item) {
      itext = (struct IntuiText *)item->ItemFill;
      textlen = itext->LeftEdge+TextLength(txtrp,
            itext->IText,(LONG)strlen(itext->IText))+width;
      maxval = (textlen<maxval)?maxval:textlen;
      item = item->NextItem;

   }
   return(maxval);
}               

/*========================================================
*
* AdjustWidths()
*
* AdjustWidths() fills in the LeftEdge field of  
* items and subitems.  
*
*=======================================================*/

VOID AdjustWidths(struct Menu *FirstMenu)
{
   REGISTER struct Menu     *menu = FirstMenu;
   REGISTER struct MenuItem *item;
   REGISTER struct MenuItem *subi;
   USHORT actual_width;
   SHORT offset;
            
        
   while (menu) {
                        
      item = menu->FirstItem;
      actual_width = 
      (menu->Width > item->Width) ? menu->Width:item->Width;
      if (item->LeftEdge < 0) 
         actual_width -= ABS(item->LeftEdge);
   
      while (item) {
         item->Width = actual_width;
         subi = item->SubItem;
         
         while (subi) {
            offset = subi->LeftEdge;
            subi->LeftEdge = (actual_width-1)*offset/100;
                        
            subi = subi->NextItem;
         }
         
         item = item->NextItem;
      }
      
      menu = menu->NextMenu;
   }               
   return;
}    
                       
/*========================================================
*
* AdjustItems()
* 
* AdjustItems sets the TopEdge,LeftEdge,Width,and Height
* fields of each item in each item box,
* and calls AdjustSubItems() for
* any possible subitems each item may have.
*
*========================================================*/     
      
VOID AdjustItems(struct RastPort *txtrp,struct MenuItem *fi,
                 struct TextAttr *atr,USHORT wdth,
USHORT hght,USHORT lvl, USHORT edge)
{
   REGISTER struct MenuItem *item = fi;
   REGISTER USHORT num = 0;
   USHORT strip_width;

   if(!fi) return;
   strip_width = MaxLength(txtrp,item,wdth);
         
   while(item) {
      item->TopEdge     = (num * hght) - lvl;
      item->LeftEdge    += edge;
      item->Width       = strip_width;
      item->Height      = hght;
      AdjustText(item,atr);
      AdjustSubItems(txtrp,item->SubItem,atr,wdth,hght,1,0);
      item = item->NextItem;
      num++;
   }
}

/*========================================================
*
* AdjustMenus()
*
* Fills in all of the positioning information which was
* left out when the menu was being constructed.
*
*=======================================================*/
                    
VOID AdjustMenus(struct Menu *firstmenu, 
                  struct TextAttr *attr)
{
   REGISTER struct Menu *menu = firstmenu;
   USHORT start = leftedge;
   USHORT width = font->tf_XSize;
   USHORT height = 
      ((font->tf_YSize < 8) ? 8 : font->tf_YSize)+2;
      
      
   while (menu) {
      menu->LeftEdge = start;
      menu->Width = TextLength(textrp,menu->MenuName,
         (LONG)strlen(menu->MenuName)) + width;
      
      AdjustItems(textrp,menu->FirstItem,attr,width,height,0,0);
      start += menu->Width;
      menu = menu->NextMenu;
   }
   menu = firstmenu;
   AdjustWidths(menu);  /* Do this last... */
   
}  /*** END AdjustMenus() ***/  

/*========================================================
*     ProcessCheckMark()
*
*  When a '.CHECKIMAGE' command is encountered, this
*  routine gets called.
*  The completed checkmark image is placed in the
*  global pointer variable 'CheckMarkImage'.
*  
*=======================================================*/

VOID ProcessCheckMark(VOID)
{
   USHORT *Imagedata = (USHORT *)AllocRemember(&RememberKey,
         (ULONG)MAX_IMAGE_SIZE/16,MEMF_CLEAR|MEMF_CHIP);
   ULONG i,bit,num_words,wordcount = 0;
   USHORT ImageWord;
   UBYTE *TextData;
  
   CheckMarkImage = NEW(Image);
  
   if (!CheckMarkImage || !Imagedata)
      CleanExit(ER_NO_MEM,FALSE,RETURN_WARN); 
            
   /* start at the next line */
   
   do {
      ++line_number; 
      fgets(cline,MAX_CHAR,input); /* get the next line */
      strcpy(dline,cline);
      TextData = ReadCheckData(cline);
      
      if(*TextData == ';' || !isgraph(*TextData)) 
         continue;   /* skip comments */                   
      
      if(*TextData == '#') break;     /* end */
      if(*TextData != '*' && *TextData != '.')
         CleanExit(ER_MISSING_END,TRUE,RETURN_WARN);
      
      /* Process image data one bit at a time */
      
      CheckMarkImage->Height++;
      num_words = 0;
            
      for(i=0;i<strlen(TextData);i++) {     
         if(TextData[i] != '*' && TextData[i] != '.') 
            continue;  
      
         /* skip leading blank space */
         
         ImageWord = 0x00;
         num_words++;
         
         for (bit=0; i<strlen(TextData),bit < 16; i++)      
         
         /* do each bit */
         
            if(TextData[i]=='.') 
               ImageWord |= (USHORT)(1 << (15-bit++));      
            else if(TextData[i]=='*') bit++
            ;
         
 
         Imagedata[wordcount++] = ImageWord;
      
      }  /* end for */
         
      
   } while (TRUE);    /* end do */

      
   CheckMarkImage->Width = num_words*16;
   CheckMarkImage->Depth = 1;
   CheckMarkImage->ImageData = Imagedata;
   CheckMarkImage->PlanePick = 1;   
      
   return;

}  /*** END ProcessCheckMark() ***/     

/*========================================================
*
* ReadCheckData()
*
* This is a special routine to read a line of image
* data (which may be blank or a comment)
*
*=======================================================*/



UBYTE *ReadCheckData(UBYTE *line)
{
   REGISTER UBYTE *pointer = line;
   REGISTER UBYTE *start;
   
   while (*pointer != '"' && *pointer != '\'' && 
          *pointer != ';' && *pointer != '\0'
          && *pointer != '*')
         
   pointer++;
   
   if( *pointer==';' || *pointer=='\0' || *pointer=='*')
   {
      *pointer = ';'; 
      return (pointer);
   }
   
   start = ++pointer;
   
   while(*pointer !='"'&& *pointer !='\''&& *pointer !='\0')
   pointer++;
   
   *pointer = '\0';
   
   return(start);   
   
}  /*** END ReadCheckData() ***/

/*========================================================
*  
*  DisplaySettings()
*
*  Prints a list of default settings and exits.
*
*
*=======================================================*/

VOID DisplaySettings(VOID)
{
   printf("\nMenuScript Version %d.%d Default settings:\n\n",
            VERSION,REVISION);
   printf("\t.width       :%4d\n",DEFAULT_WINDOW_WIDTH);
   printf("\t.height      :%4d\n",DEFAULT_WINDOW_HEIGHT);
   printf("\t.depth       :%4d\n",DEFAULT_WINDOW_DEPTH);
   printf("\t.w_detail    :%4d\n",DEFAULT_WINDOW_DETAIL_PEN);
   printf("\t.w_block     :%4d\n",DEFAULT_WINDOW_BLOCK_PEN);
   printf("\t.offset      :%4d\n",DEFAULT_OFFSET);
   printf("\t.itemedge    :%4d\n",DEFAULT_ITEMEDGE);     
   printf("\t.it_frontpen :%4d\n",DEFAULT_IT_FP);
   printf("\t.it_backpen  :%4d\n",DEFAULT_IT_BP);
   printf("\t.it_leftedge :%4d\n",DEFAULT_IT_LE);
   printf("\t.it_topedge  :%4d\n",DEFAULT_IT_TE);
   printf("\t.mode        :%s\n\n",DEFAULT_IT_MD_STR);
   printf("\t.name:        %s\n",DEFAULT_MENU_NAME);              
   printf("\tDefault Menu flags:%s\n",
                  DEFAULT_MENU_FLAGS_STR);
   printf("\tDefault MenuItem flags:%s\n\n",
                  DEFAULT_ITEM_FLAGS_STR);
   printf("\t-d   :%s\n",DEFAULT_STATE_D_STR);
   printf("\t-p   :%s\n",DEFAULT_STATE_P_STR);
   printf("\t-l   :%s\n",DEFAULT_STATE_L_STR);
   printf("\t-a   :%s\n",DEFAULT_STATE_A_STR);
   printf("\t-b   :%s\n",DEFAULT_STATE_B_STR);
   printf("\t-c   :%s\n\n",DEFAULT_STATE_C_STR);
   
   CleanExit(ER_NO_ERRORS,FALSE,RETURN_OK);

}     /*** END DisplaySettings() ***/     
      
           
         
