/* This Software is Copyrighted 1986 by Custom Services All rights to this and the generated data are the property of Custom Services and may not be used for Commercial purposes without the express written consent of Custom Services. Menu Builder V1.0 Due to the difficulty in building menus that work I attempted to automate the problem. I wanted a standard interface to the menu process with a program generating all the obvious values. This program takes a simple sequential file and generates the Menu structures for a program. Input: MENU,Name ITEM,Name,[Select],[Command] SUBI,Name,[Select],[Command] Position and Flags will be set to a reasonable default. The User may Edit the resulting source to modify the options. Name is the name of the Menu, item or Sub item. Select is an optional item which will display when the item is clicked upon. Command is the Character to use for selection of the menu item with the AMIGA key. A check will be made to see that characters are not used more than once. Only single letters A-Z are allowed. The letters M and N are not allowed since Intuition uses these for screen control. The positioning of a menu will be automatically calculated based on the length of the strings used in the menu. The widest string will be used to base the width. Most of this processing is contained in the routine Do_Output, Change it's parameters as needed. Output: Standard C source file compilable as is! The struct's Menu, MenuItem, and IntuiText will be generated as needed to define the Menu's based on the input file. You will need to include the statement: extern struct Menu *MyMenu; In your source program and call: SetMenuStrip(window ptr,MyMenu); Also, before you close your window you must call: ClearMenuStrip(window ptr); or risk a spectacular crash. I don't know why Intuition doesn't do this automatically when you close a window with a menu! */ #define EOS 0 #define CHAR_WIDTH 8 #include #include #include #define NO_ERROR 0 #define ERROR_NO_COMMA 1 #define ERROR_BAD_TEXT 2 #define ERROR_NO_MENU 3 #define ERROR_NO_ITEM 4 #define ERROR_NO_DATA 5 #define ERROR_BAD_NUMBER 6 #define ERROR_BAD_COMMAND 7 #define MAX_LINE 132 char cline[MAX_LINE]; /* input line */ char RecBuf[BUFSIZ]; /* input buffer */ char *name1; /* File name pointer */ int EndOfFile; /* true = end of file */ int lastreadsize; /* last read buffer size */ int sptr; /* current buffer pointer */ int lcnt; /* current input line count */ int Flgs[26]; /* Selected Options from Do_Arguments */ struct IntuiText *CText; /* Current Text Item pointer */ struct IntuiText *AllText; /* All text items */ struct MenuItem *CItem; /* Current Menu Item */ struct MenuItem *CSItem; /* Current Sub Menu Item */ struct Menu *CMenu, *AllMenu; /* Menu pointers */ main(argc, argv) int argc; /*number of arguments */ char *argv[]; /*array of ptrs to arg strings */ { FILE *Open(); FILE *file1; /* input File pointer */ int j, i; int result,error; char *Scan(); int GetLine(); char *cptr; /* get the file names and open the files */ /* initialize input buffers and variables*/ AllText = NULL; CText = NULL; CMenu = NULL; CItem = NULL; CSItem = NULL; AllMenu = NULL; result = NO_ERROR; error = 0; Do_Arguments(argc,argv); /* process arguments */ for (name1 = NULL, i=1; i 0) { if ( Flgs[3] ) { printf("Main:%s:%d:%8x:%8x:%8x\n",cline,j,CMenu,CItem,CSItem); }; cptr = &cline[0]; if( strncmp("MENU",cptr,4) == 0 ) { cptr = Scan(cptr,',',TRUE); result = Process_Menu(cptr); } else if ( strncmp("ITEM",cptr,4) == 0 ) { cptr = Scan(cptr,',',TRUE); result = Process_Item(cptr,0); /* do an Item */ } else if ( strncmp("SUBI",cptr,4) == 0 ) { cptr = Scan(cptr,',',TRUE); result = Process_Item(cptr,1); /* do a Sub Item */ } else /* error, bad command */ { result = ERROR_BAD_COMMAND; if( Flgs[3] ) printf(" Invalid Input at line %d\n",lcnt); }; if( result != NO_ERROR ) { error++; printf(" Line %d has syntax error:%s\n",lcnt,cptr); }; }; Close(file1); if( error == 0 ) Do_Output(); } char *Scan(ptr,c,control) char *ptr; char c; int control; { while ( *ptr != NULL && ( ( control && *ptr != c ) || ( ! control && *ptr == c) ) ) ptr++; return( ptr ); /* return the new pointer */ } GetLine(fptr,line) /* get a line from buffer */ FILE *fptr; /* file pointer if a read is needed*/ char line[]; /* destination of characters */ { char c; int idx; lcnt++; /* bump line count*/ for (idx = 0; idx < MAX_LINE; idx++ ) line[idx] = EOS; /* fill line with EOS's */ if ( sptr >= lastreadsize ) /* buffer is empty so read one */ { if ( EndOfFile ) { return(0); /* no more to read?*/ }; lastreadsize = Read(fptr, RecBuf, sizeof(RecBuf)); /* read buffer */ if (lastreadsize != sizeof(RecBuf) ) { EndOfFile = TRUE; }; sptr = 0; }; for( idx=0; idx < MAX_LINE && sptr < lastreadsize ; ) { c = RecBuf[sptr++]; if (c != 10 && c != EOS ) line[idx++] = c; /* move data */ else { while ( sptr < lastreadsize && (RecBuf[sptr] == EOS | RecBuf[sptr] == 10) ) sptr++; return(idx); }; }; if(idx == MAX_LINE | EndOfFile )return(idx); lastreadsize = Read(fptr, RecBuf, sizeof(RecBuf));/* read buffer */ if (lastreadsize != sizeof(RecBuf) ) { EndOfFile = TRUE; }; sptr = 0; for ( ;idx < MAX_LINE; ) { c = RecBuf[sptr++]; if (c != 10 && c != EOS ) line[idx++] = c; /* move data */ else { while ( sptr < lastreadsize && (RecBuf[sptr] == EOS | RecBuf[sptr] == 10) ) sptr++; return(idx); }; }; return(idx); } int Process_Menu(ptr) char *ptr; { char *tptr; int len; struct Menu *last; if( AllMenu == NULL ) { /* first menu item */ AllMenu = ( struct Menu *)malloc(sizeof(struct Menu)); CMenu = AllMenu; /* Set current pointer */ } else { /* add new one to list */ last = CMenu; CMenu = (struct Menu *)malloc(sizeof(struct Menu)); last->NextMenu = CMenu; }; /* Build Menu structure */ if( *ptr != ',')return(ERROR_NO_COMMA); ptr++; tptr = Scan(ptr,' ',TRUE); /* find end of string */ len = tptr-ptr; CMenu->MenuName = (BYTE *)malloc(len+1); stpcpy(CMenu->MenuName,ptr,len); ptr +=len; *ptr = '\0'; /* make sure it is a proper string!*/ CMenu->NextMenu = NULL; CMenu->FirstItem= NULL; CItem = NULL; CMenu->Width = len + 3 ; return(NO_ERROR); } int Process_Item(ptr,type) char *ptr; int type; /* 0 = ITEM, 1 = SUB ITEM */ { struct IntuiText *Process_Text(); struct MenuItem *ThisItem; struct MenuItem *lastI; struct MenuItem *lastSI; if( CMenu == NULL ) return(ERROR_NO_MENU); if( type == 1 && CItem == NULL )return(ERROR_NO_ITEM); if( *ptr != ',' ) return(ERROR_NO_COMMA); if( type == 0 ) { /* do an item building a MenuItem */ lastI = CItem; CSItem= NULL; /* clear current Sub Item Flag */ CItem = (struct MenuItem *)malloc(sizeof(struct MenuItem)); if( Flgs[3] ) printf("ITEM: %8x %8x %8x\n",lastI,CMenu->FirstItem,CItem); if( lastI == NULL ) { /* First Item for Menu */ CMenu->FirstItem = CItem; /* link it to the menu */ } else { lastI->NextItem = CItem; /* link it to the item list */ }; ThisItem = CItem; /* build it */ } else { /* Do a Sub Item */ lastSI = CSItem; CSItem = (struct MenuItem *)malloc(sizeof(struct MenuItem)); if( Flgs[3] ) printf("SUBI: %8x %8x %8x\n",lastSI,CItem->SubItem,CSItem); if( lastSI == NULL ) { /* First Sub Item for Menu Item */ CItem->SubItem = CSItem; /* link in the sub items */ } else { lastSI->NextItem = CSItem; }; ThisItem = CSItem; }; /* Process name select and command */ ptr++; ThisItem->ItemFill = ( APTR )Process_Text(ptr); if( Flgs[0] )printf("ItemFill:%8x\n",ThisItem->ItemFill); if( ThisItem->ItemFill == NULL )return(ERROR_BAD_TEXT); ptr = Scan(ptr,',',TRUE); /* find next comma */ if( *ptr != ',')return(ERROR_NO_COMMA); ptr++; /* Select name? */ ThisItem->SelectFill = ( APTR )Process_Text(ptr); if( Flgs[0] )printf(" SelectFill:%8x\n",ThisItem->SelectFill); ptr = Scan(ptr,',',TRUE); /* find next comma */ if( *ptr != ',')return(ERROR_NO_COMMA); ptr++; /* Command ? */ ThisItem->NextItem = NULL; ThisItem->SubItem = NULL; ThisItem->Command = *ptr; ThisItem->MutualExclude = 0L; return(NO_ERROR); } struct IntuiText *Process_Text(ptr) char *ptr; { struct IntuiText *dptr, *lasText; char *tptr; if( *ptr == ',')return(NULL); lasText = AllText; while( lasText != NULL) { CText = lasText; lasText = lasText->NextText; }; lasText = CText; CText = (struct IntuiText *)malloc(sizeof(struct IntuiText)); CText->NextText = NULL; if( Flgs[0] ) { printf("lasText:%8x CText:%8x ptr:%s\n",lasText,CText,ptr); }; if( AllText == NULL ) { AllText = CText; } else { lasText->NextText = CText; }; tptr = Scan(ptr,',',TRUE); CText->IText = (UBYTE *)malloc(tptr-ptr+1); if( Flgs[0] )printf("Length:%d IText:%8x ptr:%8x tptr:%8x\n" ,tptr-ptr+1,CText->IText,ptr,tptr); strncpy(CText->IText,ptr,tptr-ptr); if( CMenu->Width <= tptr-ptr )CMenu->Width = tptr-ptr; if( Flgs[0] )printf("len=%d Max:%d IText:%s\n", strlen(CText->IText),CMenu->Width,CText->IText); /* check for duplicate, eliminate this one if duplicate */ dptr = AllText; while ( dptr != CText ) { if( Flgs[0] ) { printf(" dptr:%8x->%s\n",dptr->IText,dptr->IText); }; if ( strcmp(dptr->IText,CText->IText) == 0 ) { if( Flgs[0] ) { printf(" Duplicate:%8x %8x %s\n", dptr,CText,dptr->IText); }; free( (char *)(CText->IText) ); free( (char *) CText ); CText = dptr; lasText->NextText = NULL; } else { dptr = dptr->NextText; }; }; if( Flgs[0] ) printf("Processed Text: %8x:%s\n",CText,CText->IText); return(CText); } Do_Output() { char nxt,quote,FLAG; char Mptr[14]; int Menu, Item, left, top, width, height; int stop; char rest[60]; /* Output the IntuiText structure first */ quote = '"'; printf("/***************************************/\n"); printf("/* Copyrighted by Custom Services 1986 */\n"); printf("/***************************************/\n"); printf("#include \n"); printf("#include \n"); CText = AllText; if( AllText != NULL) { printf("\nstruct IntuiText IText[] =\n"); printf(" {\n"); }; while( CText != NULL ) /* for all text to output */ { if( CText->NextText == NULL) { nxt = ' '; } else { nxt = ','; }; printf(" { 0, 1, JAM2, CHECKWIDTH, 0, NULL, %c%s%c}%c\n", quote,CText->IText,quote,nxt); CText = CText->NextText; }; if( AllText != NULL ) { printf(" };\n"); }; printf("\n#define EXTRA CHECKWIDTH\n"); printf("#define FLAGSA CHECKIT|ITEMTEXT|MENUTOGGLE|ITEMENABLED\n"); printf("#define FLAGSB CHECKIT|ITEMTEXT|MENUTOGGLE|ITEMENABLED|COMMSEQ\n\n"); CMenu = AllMenu; Menu = 0; left = 0; Item = 0; height = 10; while ( CMenu != NULL ) { Item = 0; CItem = CMenu->FirstItem; while ( CItem != NULL) { CSItem = CItem->SubItem; if ( CSItem != NULL ) Do_Out_Sub(Menu,Item); Item++; CItem = CItem->NextItem; }; Menu++; CMenu = CMenu->NextMenu; } CMenu = AllMenu; Menu = 0; left = 0; Item = 0; height = 10; while ( CMenu != NULL ) { Item = 0; CItem = CMenu->FirstItem; CSItem = CItem->SubItem; top = 0; printf("struct MenuItem M%d[] = \n",Menu); printf(" {\n"); top = 0; width = CMenu->Width * CHAR_WIDTH; while ( CItem != NULL ) { Item++; CSItem = CItem->SubItem; if( CItem->NextItem == NULL ) { sprintf(Mptr,"NULL "); nxt = ' '; } else { sprintf(Mptr,"&M%d[%2d]",Menu,Item); nxt = ','; }; if( CItem->SelectFill == NULL) { sprintf(rest,"NULL ,"); } else { sprintf(rest,"(APTR)&IText[%2d],",Index(CItem->SelectFill)); }; if( CItem->Command == NULL || CItem->Command == ' ') { sprintf(&rest[17],"NULL,"); FLAG = 'A'; } else { sprintf(&rest[17]," '%c',",CItem->Command); FLAG = 'B'; }; if( CSItem == NULL ) { sprintf(&rest[22],"NULL"); } else { sprintf(&rest[22],"&M%dI%d[0]",Menu, (Item-1) ); }; printf(" {%s,%3d,%3d,%3d+EXTRA,%3d,FLAGS%c,0,", Mptr,left,top,width,height,FLAG); printf("(APTR)&IText[%2d],%s}%c\n",Index(CItem->ItemFill),rest,nxt); CItem = CItem->NextItem; top = top + height + 2; }; printf(" };\n\n"); CMenu = CMenu->NextMenu; Menu++; }; CMenu = AllMenu; printf("struct Menu TheMenu[] =\n"); printf(" {\n"); left = 0; top = 0; Menu = 0; while ( CMenu != NULL ) { Menu++; width = CMenu->Width * CHAR_WIDTH; if( CMenu->NextMenu == NULL ) { sprintf(Mptr,"NULL "); nxt = ' '; } else { sprintf(Mptr,"&TheMenu[%2d]",Menu); nxt = ','; }; (void)strncpy(rest," ",25); stop = CMenu->Width - strlen(CMenu->MenuName); if( stop <= 0 ) { (void)strncpy(rest,CMenu->MenuName,25); } else { stop = stop/2; (void)strncpy(&rest[stop],CMenu->MenuName,25-stop); (void)strncat(rest," ",25); }; quote = '"'; height = 10; printf(" {%12s,%3d,%3d,%3d+EXTRA,%3d",Mptr,left,top,width,height); printf(",MENUENABLED,%c%s%c,&M%d[0]}%c\n",quote,rest,quote,(Menu-1),nxt); left = left + width + 4*CHAR_WIDTH; CMenu = CMenu->NextMenu; }; printf(" };\n\n"); printf("struct Menu *MyMenu = &TheMenu[0];"); } int Index(ptr) /* Find the position index */ struct IntuiText *ptr; { int idx; idx = 0; CText = AllText; while ( CText != NULL && ptr != CText) { if( Flgs[0] ) { printf("Index: %d, %8x:%s\n",idx,CText,CText->IText); }; idx++; CText = CText->NextText; }; return(idx); } Do_Out_Sub(Menu,Item) int Menu, Item; { int SItem; int stop, width, sleft; int top, height; char Mptr[14]; char rest[60]; char nxt,FLAG; SItem = 0; top = 0; height = 10; printf("struct MenuItem M%dI%d[] = \n",Menu,Item); printf(" {\n"); width = CMenu->Width*CHAR_WIDTH; SItem = 0; while ( CSItem != NULL ) { SItem++; if( CSItem->NextItem == NULL ) { sprintf(Mptr,"NULL "); nxt = ' '; } else { sprintf(Mptr,"&M%dI%d[%2d]",Menu,Item,SItem); nxt = ','; }; if( CSItem->SelectFill == NULL ) { sprintf(rest,"NULL ,"); } else { sprintf(rest,"(APTR)&IText[%2d],",Index(CSItem->SelectFill)); }; if( CSItem->Command == NULL || CSItem->Command == ' ') { sprintf(&rest[17],"NULL,"); FLAG = 'A'; } else { sprintf(&rest[17]," '%c',",CSItem->Command); FLAG = 'B'; }; sprintf(&rest[22],"NULL"); sleft = (width * 7)/10; stop = top + 2; printf(" {%s,%3d,%3d,%3d+EXTRA,%3d,FLAGS%c,0," ,Mptr,sleft,stop,width,height,FLAG); printf("(APTR)&IText[%2d],%s}%c\n",Index(CSItem->ItemFill),rest,nxt); CSItem = CSItem->NextItem; top = top + height; }; printf(" };\n\n"); }