home *** CD-ROM | disk | FTP | other *** search
Wrap
/************************************************************************ * * Program: Grocery.c * * Author: Brian Gragg * * Date: 11/29/92 version 0.1 * 5/15/93 version 1.4 - added create meal menu option * 10/17/93 version 1.5 - added list scroll option & sort at print * 9/19/94 version 1.6 - fixed bug in meal generation option * 3/18/95 version 1.7 - moved about requester to grocery screen * *************************************************************************/ #define DATAFILE "Grocery.data" #define BACKFILE "Grocery.data.bak" #define TEMPFILE "t:groctmp" #define MODEID HIRESLACE_KEY #define SWIDTH 640 #define SHEIGHT 400 #define SDEPTH 2 #define ASLLEFTEDGE 163 #define ASLTOPEDGE 24 #define ASLWIDTH 320 #define ASLHEIGHT 200 #define MYGAD_ITEM (0) #define MYGAD_AMOUNT (1) #define MYGAD_SIZE (2) #define MYGAD_GLIST (3) #define MYGAD_ILIST (4) #define MYGAD_MEALS (5) #define MYGAD_EDIT (6) #define MYGAD_DELETE (7) #define MYGAD_SORT (8) #define MYGAD_SORTNAME (9) #define MYGAD_AISLE (10) #define MYGAD_ADD (11) #define MAXGADGET (12) /* this should be 1 greater than last gadget id */ #define NOITEM 65535 #define OPEN 1 #define SAVE 2 #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #include <time.h> #include <ctype.h> #include <exec/types.h> #include <exec/memory.h> #include <exec/lists.h> #include <exec/nodes.h> #include <dos/dos.h> #include <libraries/asl.h> #include <intuition/intuition.h> #include <intuition/screens.h> #include <intuition/gadgetclass.h> #include <libraries/gadtools.h> #include <intuition/intuitionbase.h> #include <graphics/gfx.h> #include <graphics/gfxbase.h> #include <libraries/dos.h> #include <clib/utility_protos.h> #include <clib/alib_protos.h> #include <clib/exec_protos.h> #include <clib/dos_protos.h> #include <clib/intuition_protos.h> #include <clib/graphics_protos.h> #include <clib/gadtools_protos.h> #include <clib/asl_protos.h> /* Use SAS/C 6.0 ability to open libraries for you !! */ extern struct Library *DOSBase; extern struct Library *GadToolsBase; extern struct Library *AslBase; extern struct IntuitionBase *IntuitionBase; extern struct GfxBase *GfxBase; extern struct Library *SysBase; extern struct Library *UtilityBase; struct EasyStruct myES = { sizeof(struct EasyStruct), 0, "GroceryList", "%s", "OK", }; struct Screen *myscreen = NULL; struct Window *window = NULL; struct Menu *menuStrip = NULL; struct APTR *my_VisualInfo = NULL; struct Gadget *glist = NULL; struct List *ItemList = NULL; struct List *GrocList = NULL; struct List *MealList = NULL; struct List *AislList = NULL; struct Gadget *mygad[MAXGADGET]; struct NewGadget ng; #define NAMENODE_ID 100 /* The type of "NameNode" */ #define MEALNODE_ID 101 /* The type of "MealNode" */ struct NameNode { struct Node nn_Node; /* System Node structure */ UBYTE nn_Item[30]; /* The item (equals the node name) */ UBYTE nn_Size[10]; /* standard size (ie lbs, oz, etc) */ UBYTE nn_Amount[10]; /* usual amount */ WORD nn_Aisle; /* the aisle number where it's found*/ UBYTE nn_LongName[80]; /* the long name associated with the item */ WORD nn_ListPos; /* ordinal position in a list */ }; struct MealNode { struct Node nn_Node; /* System Node structure */ UBYTE nn_Meal[30]; /* The meal (equals node name) */ struct List *nn_MealItem; /* a sublist of items */ }; struct TextAttr Topaz80 = { "topaz.font", 8, 0, 0, }; struct NewMenu mynewmenu[] = { { NM_TITLE, "Project", 0 , 0, 0, 0,}, { NM_ITEM, "New", "N", 0, 0, 0,}, { NM_ITEM, "Open...", "O", 0, 0, 0,}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0,}, { NM_ITEM, "Save", "S", 0, 0, 0,}, { NM_ITEM, "Save As...","A", 0, 0, 0,}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0,}, { NM_ITEM, "Print", "P", 0, 0, 0,}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0,}, { NM_ITEM, "About", 0 , 0, 0, 0,}, { NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0,}, { NM_ITEM, "Quit", "Q", 0, 0, 0,}, { NM_TITLE, "Meals", 0 , 0, 0, 0,}, { NM_ITEM, "Create Meal","M", 0, 0, 0,}, }; char savefilename[256]; char aislename[30][22]; char aisleId[30]; WORD pens[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~0}; UWORD currentAisle = NOITEM; UWORD currentGroc = NOITEM; far char buffer[256], buf[256]; #ifdef LATTICE int __chkabort(void) { return(0); } /* Disable Lattice CTRL/C handling */ #endif /* VERSION STRING */ UBYTE vers[] = "\0$VER: Grocery 1.7"; char screenname[80]; char title[120]; /************ my protos *************/ VOID cleanExit(char *); /* clean up and close */ int doMenus(VOID); /* create menus */ VOID handle_window_events(VOID); /* deal with the IDCMP events */ VOID getWBPens(VOID); /* get the workbench pens */ VOID setupGadgets(VOID); /* setup the required gadgets */ VOID AddName(struct List *, UBYTE *, UBYTE *, UBYTE *, WORD); VOID AddItem(struct List *, UBYTE *, UBYTE *, UBYTE *, WORD); VOID AddAisle(struct List *, UBYTE *, WORD); struct List *AddMeal(struct List *, UBYTE *); VOID FreeMealNodes(struct List *); VOID FreeNameNodes(struct List *); VOID readData(VOID); /* reads data from DATAFILE */ VOID newMeal(VOID); /* saves the list as a meal in the database */ /*************************************************************************/ void main(int argc, char *argv[]) { LONG screenTopBorder; /* Rely on SAS/C 6.0 to open the libraries for me */ getWBPens(); strcpy(title,&vers[7]); strcat(title," - Brian Gragg March 1995"); strcpy(screenname,title); if (NULL == (myscreen = OpenScreenTags(NULL, SA_Width, SWIDTH, SA_Height, SHEIGHT, SA_DisplayID, MODEID, SA_Depth, SDEPTH, SA_Title, screenname, SA_Pens, pens, SA_ShowTitle, TRUE, TAG_END))) cleanExit("Couldn't open screen."); readData(); setupGadgets(); screenTopBorder = myscreen->WBorTop + myscreen->Font->ta_YSize +1; if (NULL == (window = OpenWindowTags(NULL, WA_Top, screenTopBorder, WA_Left, 0, WA_Height, myscreen->Height - screenTopBorder, WA_Width, myscreen->Width, WA_CustomScreen, myscreen, WA_NoCareRefresh,TRUE, WA_IDCMP, IDCMP_MENUPICK | IDCMP_MOUSEBUTTONS | LISTVIEWIDCMP | IDCMP_REFRESHWINDOW, WA_Gadgets, glist, WA_Activate, TRUE, WA_DetailPen, 3, TAG_END))) cleanExit("Couldn't open window."); GT_RefreshWindow(window, NULL); ActivateGadget(mygad[MYGAD_ITEM],window,NULL); if (doMenus()) cleanExit("Couldn't create menu strip."); handle_window_events(); cleanExit(""); } /********************************************************************* * cleanExit("message") * * clean up and exit. Print message before quiting. **********************************************************************/ VOID cleanExit(char *message) { if (strlen(message) > 1) EasyRequest(NULL, &myES, NULL, message); if (ItemList != NULL) { FreeNameNodes(ItemList); FreeMem(ItemList, sizeof(struct List)); } if (GrocList != NULL) { FreeNameNodes(GrocList); FreeMem(GrocList, sizeof(struct List)); } if (MealList != NULL) { FreeMealNodes(MealList); FreeMem(MealList, sizeof(struct List)); } if (AislList != NULL) { FreeNameNodes(AislList); FreeMem(AislList, sizeof(struct List)); } if (menuStrip != NULL) FreeMenus(menuStrip); if (glist != NULL) FreeGadgets(glist); if (my_VisualInfo != NULL) FreeVisualInfo(my_VisualInfo); if (window != NULL) CloseWindow(window); if (myscreen != NULL) CloseScreen(myscreen); /* Rely on SAS/C 6.0 to close libraries for me */ exit(0); } /********************************************************************* * getWBPens() * * get the colors from the workbench drawinfo structure **********************************************************************/ VOID getWBPens(VOID) { UBYTE *pubScreenName = "Workbench"; int i; struct Screen *pub_screen = NULL; struct DrawInfo *screen_drawinfo = NULL; /* Get a lock on the Workbench screen */ pub_screen = LockPubScreen(pubScreenName); if ( pub_screen == NULL ) { EasyRequest(NULL, &myES, NULL, "Couldn't get a lock on workbench."); for (i=0; i<4; i++) pens[i] = i; return; } screen_drawinfo = GetScreenDrawInfo(pub_screen); if ( screen_drawinfo == NULL) { UnlockPubScreen(pubScreenName,pub_screen); EasyRequest(NULL, &myES, NULL, "Couldn't get workbench's drawinfo structure."); for (i=0; i<4; i++) pens[i] = i; return; } for (i=0; pens[i] != ~0; i++) pens[i] = screen_drawinfo->dri_Pens[i]; FreeScreenDrawInfo(pub_screen,screen_drawinfo); UnlockPubScreen(pubScreenName,pub_screen); } /********************************************************************* * doMenus() * return 0=ok 1=failed **********************************************************************/ int doMenus(VOID) { if (NULL != (menuStrip = CreateMenus(mynewmenu, TAG_END))) { if (LayoutMenus(menuStrip, my_VisualInfo, TAG_END)) { if (SetMenuStrip(window, menuStrip)) { return(0); } } FreeMenus(menuStrip); } return(1); } /********************************************************************* * readData() * **********************************************************************/ VOID readData(VOID) { FILE *fileptr = NULL; /* a pointer to a file handle */ char *item, *amount, *size, meal[30]; long place; struct List *list; char *pointer; int i, j; GrocList = AllocMem(sizeof(struct List),MEMF_CLEAR); ItemList = AllocMem(sizeof(struct List),MEMF_CLEAR); MealList = AllocMem(sizeof(struct List),MEMF_CLEAR); AislList = AllocMem(sizeof(struct List),MEMF_CLEAR); if ((GrocList == NULL) || (ItemList == NULL) || (MealList == NULL) || (AislList == NULL)) cleanExit("Out of memory allocating Lists."); NewList(GrocList); NewList(ItemList); NewList(MealList); NewList(AislList); fileptr = fopen(DATAFILE,"r"); if ( fileptr == NULL ) cleanExit("Couldn't open data file."); while ((fgets(buffer,255,fileptr) != NULL) && (strlen(buffer) > 1)) { if (buffer[0] != ';') { buffer[strlen(buffer)-1] = '\0'; i = atoi(&buffer[3]); /* order id */ j = atoi(buffer); /* aisle id */ aisleId[j] = i ; strncpy(aislename[i],&buffer[6],13); AddAisle(AislList,&buffer[6], (WORD)i); } } while ((fgets(meal,29,fileptr) != NULL) && (strncmp(meal,"EXIT!",5))) { meal[strlen(meal)-1] = '\0'; list = AddMeal(MealList,meal); while ((fgets(buffer,255,fileptr) != NULL) && (strlen(buffer)>5) && (strrchr(buffer,'`') != NULL)) { pointer =strrchr(buffer,'`'); pointer[0]='\0'; place = atol(&pointer[1]); pointer =strrchr(buffer,'`'); pointer[0]='\0'; size = &pointer[1]; pointer =strrchr(buffer,'`'); pointer[0]='\0'; amount = &pointer[1]; item = buffer; AddName(list,item,amount,size,aisleId[place]); } } fgets(buffer,255,fileptr); /* read in blank line */ while ((fgets(buffer,255,fileptr) != NULL) && (strlen(buffer)>1)) { pointer =strrchr(buffer,'`'); pointer[0]='\0'; place = atol(&pointer[1]); pointer =strrchr(buffer,'`'); pointer[0]='\0'; size = &pointer[1]; pointer =strrchr(buffer,'`'); pointer[0]='\0'; amount = &pointer[1]; item = buffer; AddName(ItemList,item,amount,size,aisleId[place]); } fclose(fileptr); } /********************************************************************* * setupGadgets() * **********************************************************************/ VOID setupGadgets(VOID) { struct Gadget *gad; if (NULL == (my_VisualInfo = GetVisualInfo(myscreen, TAG_END))) cleanExit("Couldn't GetVisualInfo."); gad = CreateContext(&glist); /** ITEM GADGET **/ ng.ng_LeftEdge = 17; ng.ng_TopEdge = 348; ng.ng_Width = 215; ng.ng_Height = 21; ng.ng_GadgetText = "Item"; ng.ng_VisualInfo = my_VisualInfo; ng.ng_GadgetID = MYGAD_ITEM; ng.ng_TextAttr = &Topaz80; ng.ng_Flags = PLACETEXT_BELOW; mygad[MYGAD_ITEM] = gad = CreateGadget(STRING_KIND, gad, &ng, GA_TabCycle, TRUE, GA_Immediate, TRUE, STRINGA_ExitHelp, TRUE, TAG_END); /** AMOUNT GADGET **/ ng.ng_LeftEdge = 236; ng.ng_Width = 84; ng.ng_GadgetText = "Amount"; ng.ng_GadgetID = MYGAD_AMOUNT; mygad[MYGAD_AMOUNT] = gad = CreateGadget(STRING_KIND, gad, &ng, GA_TabCycle, TRUE, GA_Immediate, TRUE, TAG_END); ng.ng_LeftEdge = 17; /** UNITS GADGET **/ ng.ng_LeftEdge = 324; ng.ng_GadgetText = "Units"; ng.ng_GadgetID = MYGAD_SIZE, mygad[MYGAD_SIZE] = gad = CreateGadget(STRING_KIND, gad, &ng, GA_TabCycle, TRUE, GA_Immediate, TRUE, TAG_END); /** AISLE GADGET **/ ng.ng_LeftEdge = 423; ng.ng_TopEdge = 316; ng.ng_Width = 185; ng.ng_Height = 60; ng.ng_GadgetText = "Asile"; ng.ng_GadgetID = MYGAD_AISLE; mygad[MYGAD_AISLE] = gad = CreateGadget(LISTVIEW_KIND, gad, &ng, GTLV_Labels, AislList, GTLV_ScrollWidth, 18, GTLV_Top, 1, LAYOUTA_Spacing, 1, GTLV_ShowSelected, NULL, TAG_END); /** MEALS GADGET **/ ng.ng_LeftEdge = 423; ng.ng_TopEdge = 223; ng.ng_Width = 185; ng.ng_Height = 80; ng.ng_GadgetText = "Meals"; ng.ng_GadgetID = MYGAD_MEALS; mygad[MYGAD_MEALS] = gad = CreateGadget(LISTVIEW_KIND, gad, &ng, GTLV_Labels, MealList, GTLV_ScrollWidth, 18, GTLV_Top, 0, LAYOUTA_Spacing, 1, TAG_END); /** ILIST GADGET **/ ng.ng_TopEdge = 15; ng.ng_Height = 208; ng.ng_GadgetText = "Items List"; ng.ng_GadgetID = MYGAD_ILIST; ng.ng_Flags = PLACETEXT_ABOVE; mygad[MYGAD_ILIST] = gad = CreateGadget(LISTVIEW_KIND, gad, &ng, GTLV_Labels, ItemList, GTLV_ScrollWidth, 18, GTLV_Top, 0, LAYOUTA_Spacing, 1, TAG_END); /** GLIST GADGET **/ ng.ng_LeftEdge = 17; ng.ng_Width = 390; ng.ng_Height = 292; ng.ng_GadgetText = "Grocery List"; ng.ng_GadgetID = MYGAD_GLIST; mygad[MYGAD_GLIST] = gad = CreateGadget(LISTVIEW_KIND, gad, &ng, GTLV_Labels, GrocList, GTLV_ScrollWidth, 18, GTLV_Top, 0, LAYOUTA_Spacing, 1, GTLV_ShowSelected, NULL, TAG_END); /** EDIT GADGET **/ ng.ng_LeftEdge = 17; ng.ng_TopEdge = 310; ng.ng_Width = 56; ng.ng_Height = 20; ng.ng_GadgetText = "EDIT"; ng.ng_GadgetID = MYGAD_EDIT; ng.ng_Flags = PLACETEXT_IN; mygad[MYGAD_EDIT] = gad = CreateGadget(BUTTON_KIND, gad, &ng, TAG_END); /** DELETE GADGET **/ ng.ng_LeftEdge = 80; ng.ng_GadgetText = "DELETE"; ng.ng_GadgetID = MYGAD_DELETE; mygad[MYGAD_DELETE] = gad = CreateGadget(BUTTON_KIND, gad, &ng, TAG_END); /** SORT BY AISLE GADGET **/ ng.ng_LeftEdge = 143; ng.ng_Width = 94; ng.ng_GadgetText = "AISLE SORT"; ng.ng_GadgetID = MYGAD_SORT; mygad[MYGAD_SORT] = gad = CreateGadget(BUTTON_KIND, gad, &ng, TAG_END); /** SORT BY NAME GADGET **/ ng.ng_LeftEdge = 244; ng.ng_GadgetText = "NAME SORT"; ng.ng_GadgetID = MYGAD_SORTNAME; mygad[MYGAD_SORTNAME] = gad = CreateGadget(BUTTON_KIND, gad, &ng, TAG_END); /** ADD GADGET **/ ng.ng_LeftEdge = 345; ng.ng_Width = 62; ng.ng_GadgetText = "ADDITEM"; ng.ng_GadgetID = MYGAD_ADD; mygad[MYGAD_ADD] = gad = CreateGadget(BUTTON_KIND, gad, &ng, TAG_END); } /********************************************************************* * NODE FUNCTIONS * * AddName() & FreeNameNodes() & FindNode() & alphaEnqueue * * used to build and clear nodes from a list **********************************************************************/ VOID alphaEnqueue(struct List *list, struct Node *node) { /* inserts a node queued by pri then name */ struct Node *worknode; BOOL found = FALSE; worknode = list->lh_Head; /* First node */ while (worknode != NULL) { if ((worknode->ln_Pri < node->ln_Pri) || ((worknode->ln_Pri == node->ln_Pri) && (strcmp(worknode->ln_Name,node->ln_Name) > 0))) { Insert(list, node, worknode->ln_Pred); found = TRUE; break; } worknode = worknode->ln_Succ; } if ( found == FALSE ) AddTail(list,node); } /* Allocate a NameNode structure, copy the given name into the structure, * then add it the specified list. */ VOID AddName(struct List *list, UBYTE *item, UBYTE *amount, UBYTE *size, WORD aisle) { struct NameNode *namenode; if (!( namenode = AllocMem(sizeof(struct NameNode),MEMF_CLEAR) )) cleanExit("Out of memory adding a node."); strcpy(namenode->nn_Item,item); strcpy(namenode->nn_Size,size); strcpy(namenode->nn_Amount,amount); namenode->nn_Aisle = aisle; namenode->nn_Node.ln_Name = namenode->nn_Item; namenode->nn_Node.ln_Type = NAMENODE_ID; namenode->nn_Node.ln_Pri = 0; alphaEnqueue((struct List *)list,(struct Node *)namenode); } VOID AddItem(struct List *list, UBYTE *item, UBYTE *amount, UBYTE *size, WORD aisle) { struct NameNode *namenode; if (!( namenode = AllocMem(sizeof(struct NameNode),MEMF_CLEAR) )) cleanExit("Out of memory adding a node."); strcpy(namenode->nn_Item,item); strcpy(namenode->nn_Size,size); strcpy(namenode->nn_Amount,amount); namenode->nn_Aisle = aisle; namenode->nn_Node.ln_Type = NAMENODE_ID; namenode->nn_Node.ln_Pri = 0; sprintf(buffer,"%-18.18s %8.8s %-7.7s %-14.14s\0",namenode->nn_Item, namenode->nn_Amount, namenode->nn_Size, aislename[namenode->nn_Aisle]); strcat(namenode->nn_LongName,buffer); namenode->nn_Node.ln_Name = namenode->nn_LongName; AddTail((struct List *)list,(struct Node *)namenode); } VOID AddAisle(struct List *list, UBYTE *name, WORD aisle) { struct NameNode *namenode; if (!( namenode = AllocMem(sizeof(struct NameNode),MEMF_CLEAR) )) cleanExit("Out of memory adding a node."); strcpy(namenode->nn_Item,name); namenode->nn_Aisle = aisle; namenode->nn_Node.ln_Name = namenode->nn_Item; namenode->nn_Node.ln_Type = NAMENODE_ID; namenode->nn_Node.ln_Pri = 40-aisle; Enqueue((struct List *)list,(struct Node *)namenode); } struct List * AddMeal(struct List *list, UBYTE *meal) { struct MealNode *mealnode; if (!( mealnode = AllocMem(sizeof(struct MealNode),MEMF_CLEAR) )) cleanExit("Out of memory adding a meal."); strcpy(mealnode->nn_Meal,meal); mealnode->nn_Node.ln_Name = mealnode->nn_Meal; mealnode->nn_Node.ln_Type = MEALNODE_ID; mealnode->nn_Node.ln_Pri = 0; if (!(mealnode->nn_MealItem = AllocMem(sizeof(struct List),MEMF_CLEAR))) cleanExit("No memory for meal list."); NewList(mealnode->nn_MealItem); alphaEnqueue((struct List *)list,(struct Node *)mealnode); return(mealnode->nn_MealItem); } /* * Free the entire list, including the header. The header is not updated * as the list is freed. This function demonstrates how to avoid * referencing freed memory when deallocating nodes. */ VOID FreeNameNodes(struct List *list) { struct NameNode *worknode; struct NameNode *nextnode; worknode = (struct NameNode *)(list->lh_Head); /* First node */ while (nextnode = (struct NameNode *)(worknode->nn_Node.ln_Succ)) { FreeMem(worknode,sizeof(struct NameNode)); worknode = nextnode; } } VOID FreeMealNodes(struct List *list) { struct MealNode *worknode; struct MealNode *nextnode; worknode = (struct MealNode *)(list->lh_Head); /* First node */ while (nextnode = (struct MealNode *)(worknode->nn_Node.ln_Succ)) { FreeNameNodes(worknode->nn_MealItem); FreeMem(worknode->nn_MealItem, sizeof(struct List)); FreeMem(worknode,sizeof(struct MealNode)); worknode = nextnode; } } struct Node * FindNode(struct List *list, int number) { struct Node *node; int i; if (list->lh_TailPred == (struct Node *)list) return(NULL); else { for (node = list->lh_Head, i=0; i<number ; node = node->ln_Succ, i++) ; return(node); } } /********************************************************************* * getFile(Prompt) * * gets a file using the ASL file requester & the prompt **********************************************************************/ BPTR getFile(char *prompt,int type) { struct FileRequester *fr; static BYTE savefile[100] = ""; static BYTE savedir[255] = ""; char doit[10]; ULONG fileflag; long mode; BPTR fh = -1L; if (type == OPEN) { strcpy(doit,"OPEN"); fileflag = 0L; } else { strcpy(doit,"SAVE"); fileflag = FILF_SAVE; } if (fr = (struct FileRequester *) AllocAslRequestTags(ASL_FileRequest, ASL_Hail, (ULONG)prompt, ASL_Height, 200, ASL_Width, 320, ASL_LeftEdge, 163, ASL_TopEdge, 50, ASL_OKText, (ULONG)doit, ASL_CancelText, (ULONG)"CANCEL", ASL_Window, window, ASL_File, savefile, ASL_Dir, savedir, ASL_FuncFlags, fileflag, TAG_DONE)) { if (AslRequest(fr,NULL)) { strcpy(savedir, fr->rf_Dir); strcpy(savefile, fr->rf_File); /* setup filename and load it */ strcpy(buffer,fr->rf_Dir); if (AddPart(buffer,fr->rf_File,255)) { if (type == OPEN) mode = MODE_OLDFILE; else mode = MODE_NEWFILE; fh = Open(buffer,mode); strcpy(savefilename,buffer); sprintf(screenname,"%s [FILE: %s]",title,fr->rf_File); ShowTitle(myscreen,TRUE); } } else fh = 0L; /* CANCEL */ FreeAslRequest(fr); } return(fh); } /********************************************************************* * Menu selection (NEW) * **********************************************************************/ VOID doNew(VOID) { GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, ~0, TAG_DONE); FreeNameNodes(GrocList); FreeMem(GrocList, sizeof(struct List)); if (!(GrocList = AllocMem(sizeof(struct List),MEMF_CLEAR))) cleanExit("No memory for Grocery list."); NewList(GrocList); GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, GrocList, TAG_DONE); } /********************************************************************* * Menu selection (OPEN) * **********************************************************************/ VOID doOpen(VOID) { BPTR pfile; char *pointer; char *item, *amount, *size; long place = 0L; if (-1 == (pfile = getFile("Select Save Open:",OPEN))) { sprintf(buf,"Couldn't open file '%s'.",buffer); EasyRequest(window, &myES, NULL, buf); } doNew(); GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, ~0, TAG_DONE); while (FGets(pfile,buffer,255) != NULL) { pointer =strrchr(buffer,'`'); pointer[0]='\0'; place = atol(&pointer[1]); pointer =strrchr(buffer,'`'); pointer[0]='\0'; size = &pointer[1]; pointer =strrchr(buffer,'`'); pointer[0]='\0'; amount = &pointer[1]; item = buffer; AddItem(GrocList,item,amount,size,aisleId[place]); } GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, GrocList, TAG_DONE); Close(pfile); } /********************************************************************* * Menu selection (SAVE & SAVE AS) * **********************************************************************/ VOID doSave(VOID) { BPTR pfile; struct NameNode *node; int i; if (GrocList->lh_TailPred == (struct Node *)GrocList) return; /* empty list */ if (savefilename[0] == '\0') { pfile = getFile("Select Save File:",SAVE); if (pfile == -1 ) { sprintf(buf,"Couldn't open file '%s'\nIt may already exist.",buffer); EasyRequest(window, &myES, NULL, buf); } if (pfile == 0 ) return; } else { DeleteFile(savefilename); if (-1 == (pfile = Open(savefilename,MODE_NEWFILE))) { sprintf(buffer,"Couldn't open file '%s'.",savefilename); EasyRequest(window, &myES, NULL, buffer); } } if (pfile == -1) return; for (node=(struct NameNode *)GrocList->lh_Head ; node->nn_Node.ln_Succ ; node = (struct NameNode *)node->nn_Node.ln_Succ) { for (i = 0; i < 30; i++) if (aisleId[i] == node->nn_Aisle) break; sprintf(buffer, "%s`%s`%s`%d\n", node->nn_Item, node->nn_Amount, node->nn_Size, i); if (-1 == Write(pfile, buffer, strlen(buffer))) { EasyRequest(window, &myES, NULL, "Save File Failed."); break; } } strcpy(buf,screenname); sprintf(screenname,"Saved to file: %s",savefilename); ShowTitle(myscreen,TRUE); strcpy(screenname,buf); Close(pfile); } /********************************************************************* * Sort List * doSort(ID) ID= MYGAD_SORT or MYGAD_SORTNAME **********************************************************************/ VOID doSort(int ID) { struct NameNode *node, *nextnode; struct List *list; if (GrocList->lh_TailPred == (struct Node *)GrocList) return; /* empty list */ if (!(list = AllocMem(sizeof(struct List),MEMF_CLEAR))) cleanExit("No memory for list."); NewList(list); GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, ~0, TAG_DONE); for (nextnode=node=(struct NameNode *)GrocList->lh_Head ; nextnode->nn_Node.ln_Succ ; node = nextnode) { nextnode = (struct NameNode *)node->nn_Node.ln_Succ; Remove((struct Node *)node); if (ID == MYGAD_SORT) node->nn_Node.ln_Pri = 40-node->nn_Aisle; else node->nn_Node.ln_Pri = 0; alphaEnqueue(list,(struct Node *)node); } FreeMem(GrocList, sizeof(struct List)); GrocList = list; GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, GrocList, TAG_DONE); currentGroc = NOITEM; ActivateGadget(mygad[MYGAD_ITEM],window,NULL); } /********************************************************************* * Menu selection (PRINT) * **********************************************************************/ VOID doPrint(VOID) { BPTR pfile; struct NameNode *node; char line[70]; doSort(MYGAD_SORT); if (GrocList->lh_TailPred == (struct Node *)GrocList) return; /* empty list */ if (!(pfile = Open( "PRT:", MODE_NEWFILE))) EasyRequest(window, &myES, NULL, "Could not access printer."); Write(pfile, "zw", 8L); for (node=(struct NameNode *)GrocList->lh_Head; node->nn_Node.ln_Succ ; node = (struct NameNode *)node->nn_Node.ln_Succ) { if (node->nn_Aisle == ((struct NameNode *)node->nn_Node.ln_Succ)->nn_Aisle) strcpy(line,""); else strcpy(line,""); sprintf(buffer, "%s%10.10s %-30.30s %-10.10s %-21.21s\n", line,node->nn_Amount, node->nn_Item, node->nn_Size, aislename[node->nn_Aisle]); if (-1 == Write(pfile, buffer, strlen(buffer))) { EasyRequest(window, &myES, NULL, "Printing Failed."); break; } } Write(pfile,"zw",8L); Close(pfile); } /********************************************************************* * node = findBestFit(string) * * finds the item whose name best fist the string. **********************************************************************/ struct NameNode * findBestFit(char *namestring) { struct NameNode *node; int i = 0; for (node=(struct NameNode *)ItemList->lh_Head ; node->nn_Node.ln_Succ, Stricmp(node->nn_Item,namestring)<0; node = (struct NameNode *)node->nn_Node.ln_Succ, i++); node->nn_ListPos = i; return(node); } /********************************************************************* * getItem(node) * * gets the info from the item and loads item,amount,size,location * requesters **********************************************************************/ VOID getItem(struct NameNode *node) { GT_SetGadgetAttrs(mygad[MYGAD_ITEM],window,NULL, GTST_String, node->nn_Item, TAG_DONE); GT_SetGadgetAttrs(mygad[MYGAD_AMOUNT],window,NULL, GTST_String, node->nn_Amount, TAG_DONE); GT_SetGadgetAttrs(mygad[MYGAD_SIZE],window,NULL, GTST_String, node->nn_Size, TAG_DONE); GT_SetGadgetAttrs(mygad[MYGAD_AISLE],window,NULL, GTLV_Selected, node->nn_Aisle, TAG_DONE); /* turning this on will cause the item list to move the clicked on selection to the top each time. GT_SetGadgetAttrs(mygad[MYGAD_ILIST],window,NULL, GTLV_Top, node->nn_ListPos, TAG_DONE); */ ActivateGadget(mygad[MYGAD_AMOUNT],window,NULL); currentAisle = node->nn_Aisle; } /********************************************************************* * MEALS -> CREATE MEAL menu option * **********************************************************************/ VOID newMeal(VOID) { FILE *fileptr = NULL; /* a pointer to a file handle */ FILE *tempptr = NULL; struct List *list; struct NameNode *node; int i; struct EasyStruct yesno = { sizeof(struct EasyStruct), 0, "GroceryList", "%s", "OK|CANCEL", }; if (GrocList->lh_TailPred == (struct Node *)GrocList) { EasyRequest(window, &myES, NULL, "Grocery List empty.\nTo use this option, fill the grocery list with the\nitems in the meal and put the meal name\nin the ITEM box. Then select CREATE MEAL"); return; /* empty list */ } if (strlen(((struct StringInfo *)mygad[MYGAD_ITEM]->SpecialInfo)->Buffer) < 1) { EasyRequest(window, &myES, NULL, "Item Field empty.\nTo use this option, fill the grocery list with the\nitems in the meal and put the meal name\nin the ITEM box. Then select CREATE MEAL"); return; /* empty list */ } sprintf(buffer,"Copy current list to a meal item\ncalled %s?", ((struct StringInfo *)mygad[MYGAD_ITEM]->SpecialInfo)->Buffer); if (0L == EasyRequest(window, &yesno, NULL, buffer)) return; /* OPEN FILES */ fileptr = fopen(DATAFILE,"r"); if ( fileptr == NULL ) cleanExit("Couldn't open data file."); tempptr = fopen(TEMPFILE,"w"); if ( tempptr == NULL ) { fclose(fileptr); fileptr = 0L; remove(TEMPFILE); EasyRequest(window, &myES, NULL, "Couldn't open temporary file."); return; } /* COPY THE DATA FILE UP TO THE END OF THE MEALS SECTION */ while ((fgets(buffer,255,fileptr) != NULL) && (strncmp(buffer,"EXIT!",5) != 0)) { fputs(buffer,tempptr); } /* END OF MEALS SECTION NOT FOUND !!!!! WE HAVE A PROBLEM */ if (strncmp(buffer,"EXIT!",5) != 0) { fclose(fileptr); fclose(tempptr); fileptr = 0L; tempptr = 0L; remove(TEMPFILE); EasyRequest(window, &myES, NULL, "Error reading data file. EXIT! line not found"); return; } /* OKAY, LETS ADD THE MEAL */ /* ADD MEAL NAME */ fputs(((struct StringInfo *)mygad[MYGAD_ITEM]->SpecialInfo)->Buffer,tempptr); fputc('\n',tempptr); GT_SetGadgetAttrs(mygad[MYGAD_MEALS],window,NULL, GTLV_Labels, ~0, TAG_DONE); list = AddMeal(MealList,strcat(((struct StringInfo *)mygad[MYGAD_ITEM]->SpecialInfo)->Buffer, strnset(buffer,' ',29-strlen(((struct StringInfo *)mygad[MYGAD_ITEM]->SpecialInfo)->Buffer)))); /* NOW ADD THE ITEMS */ for (node=(struct NameNode *)GrocList->lh_Head; node->nn_Node.ln_Succ ; node = (struct NameNode *)node->nn_Node.ln_Succ) { for (i=0;i<31;i++) if (aisleId[i] == node->nn_Aisle) break; if (1 > fprintf(tempptr, "%s`%s`%s`%d\n", node->nn_Item,node->nn_Amount, node->nn_Size, i)) { fclose(tempptr); fclose(fileptr); tempptr = 0L; fileptr = 0L; remove(TEMPFILE); EasyRequest(window, &myES, NULL, "Couldn't write to temp file."); return; } AddName(list,node->nn_Item,node->nn_Amount,node->nn_Size, node->nn_Aisle); } /* NOW COPY THE REST OF THE DATA */ GT_SetGadgetAttrs(mygad[MYGAD_MEALS],window,NULL, GTLV_Labels, MealList, TAG_DONE); fputc('\n',tempptr); fputs("EXIT!\n",tempptr); while (fgets(buffer,255,fileptr) != NULL) { fputs(buffer,tempptr); } /* CLEAN UP FILES */ fclose(fileptr); fileptr=0L; fclose(tempptr); tempptr=0L; remove(BACKFILE); rename(DATAFILE, BACKFILE); sprintf(buffer,"copy %s %s \012delete >nil: %s",TEMPFILE, DATAFILE, TEMPFILE); Execute(buffer,0L,0L); } /********************************************************************* * handle_window_events() * **********************************************************************/ VOID handle_window_events(VOID) { struct IntuiMessage *msg; SHORT done; UWORD menuNumber; UWORD menuNum; UWORD itemNum; UWORD subNum; WORD mousex, mousey; ULONG class; USHORT code; struct MenuItem *item; char buffer[60]; struct MealNode *mnode; struct NameNode *node, *nextnode; struct List *list; struct Gadget *gad; char *items, *amounts, *sizes; BPTR pfile; int i; done = FALSE; while (FALSE == done) { /* we only have one signal bit, so we do not have to check which ** bit broke the Wait(). */ Wait(1L << window->UserPort->mp_SigBit); while ( (FALSE == done) && (NULL != (msg = (struct IntuiMessage *)GT_GetIMsg(window->UserPort)))) { class = msg->Class; code = msg->Code; mousex= msg->MouseX; mousey= msg->MouseY; gad = (struct Gadget *)msg->IAddress; /*not valid for non-gadget event*/ GT_ReplyIMsg(msg); switch (class) { case IDCMP_MENUPICK: menuNumber = code; while (menuNumber != MENUNULL) { item = ItemAddress(menuStrip, menuNumber); /* process the item here! */ menuNum = MENUNUM(menuNumber); itemNum = ITEMNUM(menuNumber); subNum = SUBNUM(menuNumber); /* stop if quit is selected. */ switch ( menuNum ) { case 0: /*** PROJECT ***/ switch ( itemNum ) { case 0: /* NEW */ doNew(); break; case 1: /* OPEN... */ doOpen(); break; case 4: /* SAVE AS ... */ savefilename[0] = '\0'; case 3: /* SAVE */ doSave(); break; case 6: /* PRINT */ doPrint(); break; case 8: /* ABOUT */ sprintf(buffer,"%s\nBrian Gragg Oct 1993 ",&vers[7]); EasyRequest(window, &myES, NULL,buffer); break; case 10: /* QUIT */ done = TRUE; break; } break; case 1: /*** MEALS ***/ switch (itemNum ) { case 0: /* CREATE MEAL */ newMeal(); break; } case 2: /*** OPTIONS ***/ switch (itemNum ) { case 0: /* SCROLLING LIST */ break; } } menuNumber = item->NextSelect; } break; case IDCMP_GADGETUP: switch (gad->GadgetID) { case MYGAD_MEALS: GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, ~0, TAG_DONE); if ((mnode = (struct MealNode *)FindNode(MealList,code))==NULL) break; /* not a valid mnode */ list = mnode->nn_MealItem; if (list->lh_TailPred == (struct Node *)list) break; /* empty list */ for (node=(struct NameNode *)list->lh_Head ; node->nn_Node.ln_Succ ; node = (struct NameNode *)node->nn_Node.ln_Succ) AddItem(GrocList,node->nn_Item,node->nn_Amount, node->nn_Size,node->nn_Aisle); GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, GrocList, TAG_DONE); currentGroc = NOITEM; ActivateGadget(mygad[MYGAD_ITEM],window,NULL); break; case MYGAD_ILIST: if (NULL == (node = (struct NameNode *)FindNode(ItemList,code))) break; /* not a valid node */ node->nn_ListPos = code; getItem(node); break; case MYGAD_ITEM: if (code == 0x5F) /* HELP key */ { node = findBestFit(((struct StringInfo *)mygad[MYGAD_ITEM]->SpecialInfo)->Buffer); if (node != NULL) { getItem(node); GT_SetGadgetAttrs(mygad[MYGAD_ILIST],window,NULL, GTLV_Top, node->nn_ListPos, TAG_DONE); } break; } case MYGAD_AMOUNT: case MYGAD_SIZE: if (code == 9) break; /* ignore tab key */ items = ((struct StringInfo *)mygad[MYGAD_ITEM]->SpecialInfo)->Buffer; amounts = ((struct StringInfo *)mygad[MYGAD_AMOUNT]->SpecialInfo)->Buffer; sizes = ((struct StringInfo *)mygad[MYGAD_SIZE]->SpecialInfo)->Buffer; if ((strlen(items) < 3) || (strlen(amounts) < 0) || (strlen(sizes) < 1) || (currentAisle == NOITEM)) { DisplayBeep(myscreen); break; } GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, ~0, TAG_DONE); AddItem(GrocList, items, amounts, sizes, currentAisle); GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, GrocList, TAG_DONE); currentGroc = NOITEM; /* now clear the string gadgets */ GT_SetGadgetAttrs(mygad[MYGAD_ITEM],window,NULL, GTST_String, "", TAG_DONE); GT_SetGadgetAttrs(mygad[MYGAD_AMOUNT],window,NULL, GTST_String, "", TAG_DONE); GT_SetGadgetAttrs(mygad[MYGAD_SIZE],window,NULL, GTST_String, "", TAG_DONE); GT_SetGadgetAttrs(mygad[MYGAD_AISLE],window,NULL, GTLV_Selected, NOITEM, TAG_DONE); ActivateGadget(mygad[MYGAD_ITEM],window,NULL); currentAisle = NOITEM; break; case MYGAD_AISLE: currentAisle = code; ActivateGadget(mygad[MYGAD_AMOUNT],window,NULL); break; case MYGAD_EDIT: if (NULL == (node = (struct NameNode *)FindNode(GrocList,currentGroc))) break; /* not a valid node */ GT_SetGadgetAttrs(mygad[MYGAD_ITEM],window,NULL, GTST_String, node->nn_Item, TAG_DONE); GT_SetGadgetAttrs(mygad[MYGAD_AMOUNT],window,NULL, GTST_String, node->nn_Amount, TAG_DONE); GT_SetGadgetAttrs(mygad[MYGAD_SIZE],window,NULL, GTST_String, node->nn_Size, TAG_DONE); GT_SetGadgetAttrs(mygad[MYGAD_AISLE],window,NULL, GTLV_Selected, node->nn_Aisle, TAG_DONE); ActivateGadget(mygad[MYGAD_AMOUNT],window,NULL); currentAisle = node->nn_Aisle; case MYGAD_DELETE: if (NULL == (node = (struct NameNode *)FindNode(GrocList,currentGroc))) break; /* not a valid node */ GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, ~0, TAG_DONE); Remove((struct Node *)node); GT_SetGadgetAttrs(mygad[MYGAD_GLIST],window,NULL, GTLV_Labels, GrocList, TAG_DONE); FreeMem(node,sizeof(struct NameNode)); currentGroc = NOITEM; ActivateGadget(mygad[MYGAD_ITEM],window,NULL); break; case MYGAD_GLIST: currentGroc = code; ActivateGadget(mygad[MYGAD_ITEM],window,NULL); break; case MYGAD_SORT: case MYGAD_SORTNAME: doSort((int)gad->GadgetID); break; case MYGAD_ADD: items = ((struct StringInfo *)mygad[MYGAD_ITEM]->SpecialInfo)->Buffer; amounts = ((struct StringInfo *)mygad[MYGAD_AMOUNT]->SpecialInfo)->Buffer; sizes = ((struct StringInfo *)mygad[MYGAD_SIZE]->SpecialInfo)->Buffer; if ((strlen(items) < 3) || (strlen(amounts) < 1) || (strlen(sizes) < 1) || (currentAisle == NOITEM)) { DisplayBeep(myscreen); /* bad data */ break; } /* Save the new item to the DATAFILE */ if (!(pfile = Open(DATAFILE,MODE_OLDFILE))) { EasyRequest(window, &myES, NULL, "Couldn't open data file"); break; } Seek(pfile,0,OFFSET_END); for (i = 0; i < 30; i++) if (aisleId[i] == currentAisle) break; sprintf(buffer, "%s`%s`%s`%d\n", items, amounts, sizes, i); Write(pfile, buffer, strlen(buffer)); Close(pfile); /* Update the Item List */ GT_SetGadgetAttrs(mygad[MYGAD_ILIST],window,NULL, GTLV_Labels, ~0, TAG_DONE); AddName(ItemList, items, amounts, sizes, currentAisle); GT_SetGadgetAttrs(mygad[MYGAD_ILIST],window,NULL, GTLV_Labels, ItemList, TAG_DONE); ActivateGadget(mygad[MYGAD_AMOUNT],window,NULL); break; default: break; } case IDCMP_REFRESHWINDOW: GT_BeginRefresh(window); GT_EndRefresh(window, TRUE); break; default: break; } } } }