/* ------------------------------------ *** Little Black Book © 1987 Lcc *** ------------------------------------ This program is presented in the spirit of keeping shareware alive. You may freely copy and distribute, for non-commercial purposes, both Little Black Book and the limited file handler library (bfile.lib) provided that this documentation accompanies the programs and that no charge is made for copying and distribution. If you find these programs useful please send your contribution to the address below. If you desire the full-blown bfile library on disk complete with source code (bfile is written in 'C' and is not Amiga specific) - Please send the nominal fee of $30¹ to: Craig Nelson Log Cabin Computer 921 Arcola Ct PP Granbury, TX 76048 ¹ A bona fide job offer may be substituted for cash as this programmer is currently unemployed (817) 573-7304. Notes, caveats and stuff -------------------------- * Because of special keyboard/mouse handling, runs only under WorkBench release 1.2 (this does not apply to bfile.lib) * Set up for 80 column because that's my preference * If the display flashes it's either your imagination or the beginning or end of file has been reached * For the most part, either the keyboard or the mouse may be used interchangeably - you'll get the idea just by playing around move pointer to the bottom of window when the pointer is at the bottom of window enters edit mode exits edit mode restores a field clears a field next record previous record F1 - 'FND' finds the first occurence > or = to entry typed (the record key is upper case so 'johnson' = 'JOHNSON') F2 - 'SAV' saves changes made to an existing record F3 - 'ADD' adds a new record F4 - 'DEL' deletes a record - - - */ #include #include #define BLUP 0 #define WHTP 1 #define BLKP 2 #define YLWP 3 #define MESSAGE (1 << wdw->UserPort->mp_SigBit) #define IGNORE_MSG ((qual & 0x0200) || (code & 0x80)) /* Key up, repeat */ #define ABORT_MSG (qual & 0x2008) /* CTRL, RMB */ #define FND_KEY 0x50 /* F1 */ #define SAV_KEY 0x51 /* F2 */ #define ADD_KEY 0x52 /* F3 */ #define DEL_KEY 0x53 /* F4 */ #define EDT_KEY 0x44 /* Return */ #define PRV_KEY 0x4F /* Left arrow */ #define NXT_KEY 0x4E /* Right arrow */ #define NAM_GAD 1 #define ADR_GAD 2 #define CIT_GAD 3 #define STA_GAD 4 #define ZIP_GAD 5 #define PHN_GAD 6 #define NOT_GAD 7 #define FND_GAD 8 #define SAV_GAD 9 #define ADD_GAD 10 #define DEL_GAD 11 #define PRV_GAD 12 #define NXT_GAD 13 #define NEG_GAD 14 #define POS_GAD 15 #define STR_GAD 7 /* End of string gadgets */ #define WDW_GAD 13 /* End of normal gadgets */ /*------------------------ Required by bfile.lib -------------------------*/ extern int BFILE_OK; typedef char BFILE[100]; /*----------------------- Database file definition -----------------------*/ #define DUP 1 /* Duplicate records OK */ typedef char BKEY[26]; /* Record key */ struct DataRec { char Name[26], Addr[26], City[15], State[3], Zip[6], Phone[15], Note[81]; } BookRec, SaveRec; BFILE BookDataFile; BFILE BookIndexFile; BKEY BookKey; int BookRecNum; /*---------------------- Special external functions ----------------------*/ extern struct MsgPort *CreatePort(); extern struct IOStdReq *CreateStdIO(); extern struct TextFont *OpenFont(); /*----------------------------- Global data ------------------------------*/ struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Window *wdw; struct IntuiMessage *msg; struct RastPort *rp; struct MsgPort *dev; struct IOStdReq *req; struct TextFont *font; ULONG class; USHORT code; USHORT qual; APTR iadr; USHORT gid; short find_flag; char Undo[81]; char Note[26]; char used[8]; char wdwttl[] = { " Little Black Book © 1987 Lcc " }, scrttl[] = { "Little Black Book © 1987 Lcc (817) 573-7304 WB 1.2 80 col" }; struct TextAttr attr = { "topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT }; struct InputEvent epos = { NULL, IECLASS_POINTERPOS, 0, IECODE_NOBUTTON, 0,0,0,0 }, ebut = { NULL, IECLASS_POINTERPOS, 0, IECODE_LBUTTON, 0,0,0,0 }; USHORT prv_pix[] = { 0xFE3F,0xF87F,0xC0FF,0x0000,0xC0FF,0xF87F,0xFE3F }, nxt_pix[] = { 0xFC7F,0xFE1F,0xFF03,0x0000,0xFF03,0xFE1F,0xFC7F }; struct Image prv_img = { 4,0, 16,7,1, (USHORT *) &prv_pix, 0x2,0x0, NULL }, nxt_img = { 4,0, 16,7,1, (USHORT *) &nxt_pix, 0x2,0x0, NULL }; SHORT c03_pts[] = { -3,-1, 28,-1, 28,10, -3,10, -3,-1 }, c06_pts[] = { -3,-1, 52,-1, 52,10, -3,10, -3,-1 }, c15_pts[] = { -3,-1, 124,-1, 124,10, -3,10, -3,-1 }, c26_pts[] = { -3,-1, 212,-1, 212,10, -3,10, -3,-1 }, sel_pts[] = { -3,-1, 52,-1, 52, 9, -3, 9, -3,-1 }; struct Border c03_brdr = { -1,-1, BLUP,BLKP,JAM1, 5,(SHORT *) &c03_pts, NULL }, c06_brdr = { -1,-1, BLUP,BLKP,JAM1, 5,(SHORT *) &c06_pts, NULL }, c15_brdr = { -1,-1, BLUP,BLKP,JAM1, 5,(SHORT *) &c15_pts, NULL }, c26_brdr = { -1,-1, BLUP,BLKP,JAM1, 5,(SHORT *) &c26_pts, NULL }, sel_brdr = { -1,-1, YLWP,BLKP,JAM1, 5,(SHORT *) &sel_pts, NULL }, neg_brdr = { -1,-1, BLKP,BLKP,JAM1, 5,(SHORT *) &c03_pts, NULL }; struct StringInfo nam_info = { BookRec.Name , Undo, 0,26,0,0,0,0,0,0, NULL,0,NULL }, adr_info = { BookRec.Addr , Undo, 0,26,0,0,0,0,0,0, NULL,0,NULL }, cit_info = { BookRec.City , Undo, 0,15,0,0,0,0,0,0, NULL,0,NULL }, sta_info = { BookRec.State, Undo, 0, 3,0,0,0,0,0,0, NULL,0,NULL }, zip_info = { BookRec.Zip , Undo, 0, 6,0,0,0,0,0,0, NULL,0,NULL }, phn_info = { BookRec.Phone, Undo, 0,15,0,0,0,0,0,0, NULL,0,NULL }, not_info = { BookRec.Note , Undo, 0,81,0,0,0,0,0,0, NULL,0,NULL }; struct IntuiText nam_text = { BLUP,BLKP,JAM1, -44, 0,&attr, "Name" , NULL }, adr_text = { BLUP,BLKP,JAM1, -44, 0,&attr, "Addr" , NULL }, cit_text = { BLUP,BLKP,JAM1, -44, 0,&attr, "City" , NULL }, sta_text = { BLUP,BLKP,JAM1, -52, 0,&attr, "State" , NULL }, zip_text = { BLUP,BLKP,JAM1, -44, 0,&attr, "Zip" , NULL }, phn_text = { BLUP,BLKP,JAM1, -28, 0,&attr, "Ph" , NULL }, not_text = { BLUP,BLKP,JAM1, -44, 0,&attr, "Note" , NULL }, fnd_text = { BLUP,BLKP,JAM1, 0, 0,&attr, "F1=FND" , NULL }, sav_text = { BLUP,BLKP,JAM1, 0, 0,&attr, "F2=SAV" , NULL }, add_text = { BLUP,BLKP,JAM1, 0, 0,&attr, "F3=ADD" , NULL }, del_text = { BLUP,BLKP,JAM1, 0, 0,&attr, "F4=DEL" , NULL }, usd_text = { BLUP,BLKP,JAM2, 0, 0,&attr, used , NULL }, neg_text = { BLKP,BLKP,JAM1, 4, 0,&attr, "No" , NULL }, pos_text = { BLKP,BLKP,JAM1, 0, 0,&attr, "Yes" , NULL }, avf_text = { BLKP,BLKP,JAM1, 48, 3,&attr, "Add Duplicate?" , NULL }, dvf_text = { BLKP,BLKP,JAM1, 48, 3,&attr, "Delete Record?" , NULL }, svf_text = { BLKP,BLKP,JAM1, 48, 3,&attr, "Changed - Save?", NULL }, not_disp = { WHTP,BLUP,JAM2, 56,71,&attr, Note , NULL }, phn_disp = { WHTP,BLUP,JAM2, 144,57,&attr, BookRec.Phone , ¬_disp }, zip_disp = { WHTP,BLUP,JAM2, 56,57,&attr, BookRec.Zip , &phn_disp }, sta_disp = { WHTP,BLUP,JAM2, 240,43,&attr, BookRec.State , &zip_disp }, cit_disp = { WHTP,BLUP,JAM2, 56,43,&attr, BookRec.City , &sta_disp }, adr_disp = { WHTP,BLUP,JAM2, 56,29,&attr, BookRec.Addr , &cit_disp }, nam_disp = { WHTP,BLUP,JAM2, 56,15,&attr, BookRec.Name , &adr_disp }; struct Gadget nam_gdgt = { NULL, 56,15,208,8, GADGHCOMP, RELVERIFY, STRGADGET, (APTR) &c26_brdr, NULL, &nam_text, 0, (APTR) &nam_info, NAM_GAD, NULL }, adr_gdgt = { NULL, 56,29,208,8, GADGHCOMP, RELVERIFY, STRGADGET, (APTR) &c26_brdr, NULL, &adr_text, 0, (APTR) &adr_info, ADR_GAD, NULL }, cit_gdgt = { NULL, 56,43,120,8, GADGHCOMP, RELVERIFY, STRGADGET, (APTR) &c15_brdr, NULL, &cit_text, 0, (APTR) &cit_info, CIT_GAD, NULL }, sta_gdgt = { NULL, 240,43,24,8, GADGHCOMP, RELVERIFY, STRGADGET, (APTR) &c03_brdr, NULL, &sta_text, 0, (APTR) &sta_info, STA_GAD, NULL }, zip_gdgt = { NULL, 56,57,48,8, GADGHCOMP, RELVERIFY, STRGADGET, (APTR) &c06_brdr, NULL, &zip_text, 0, (APTR) &zip_info, ZIP_GAD, NULL }, phn_gdgt = { NULL,144,57,120,8, GADGHCOMP, RELVERIFY, STRGADGET, (APTR) &c15_brdr, NULL, &phn_text, 0, (APTR) &phn_info, PHN_GAD, NULL }, not_gdgt = { NULL, 56,71,208,8, GADGHCOMP, RELVERIFY, STRGADGET, (APTR) &c26_brdr, NULL, ¬_text, 0, (APTR) ¬_info, NOT_GAD, NULL }, fnd_gdgt = { NULL, 15,87,48,7, GADGHCOMP, RELVERIFY, BOOLGADGET, (APTR) &sel_brdr, NULL, &fnd_text, 0, (APTR) NULL, FND_GAD, NULL }, sav_gdgt = { NULL, 76,87,48,7, GADGHCOMP, RELVERIFY, BOOLGADGET, (APTR) &sel_brdr, NULL, &sav_text, 0, (APTR) NULL, SAV_GAD, NULL }, add_gdgt = { NULL, 137,87,48,7, GADGHCOMP, RELVERIFY, BOOLGADGET, (APTR) &sel_brdr, NULL, &add_text, 0, (APTR) NULL, ADD_GAD, NULL }, del_gdgt = { NULL, 198,87,48,7, GADGHCOMP, RELVERIFY, BOOLGADGET, (APTR) &sel_brdr, NULL, &del_text, 0, (APTR) NULL, DEL_GAD, NULL }, prv_gdgt = { NULL, 259,87,24,7, GADGIMAGE | GADGHCOMP, RELVERIFY, BOOLGADGET, (APTR) &prv_img, NULL, NULL, 0, (APTR) NULL, PRV_GAD, NULL }, nxt_gdgt = { NULL, 283,87,24,7, GADGIMAGE | GADGHCOMP, RELVERIFY, BOOLGADGET, (APTR) &nxt_img, NULL, NULL, 0, (APTR) NULL, NXT_GAD, NULL }, neg_gdgt = { NULL, 222,3,24,8, GADGHNONE, RAWKEY | TOGGLESELECT | ENDGADGET, BOOLGADGET | REQGADGET, (APTR) &neg_brdr, NULL, &neg_text, 0, (APTR) NULL, NEG_GAD, NULL }, pos_gdgt = { &neg_gdgt, 182,3,24,8, GADGHNONE, RAWKEY | TOGGLESELECT | ENDGADGET, BOOLGADGET | REQGADGET, (APTR) &neg_brdr, NULL, &pos_text, 0, (APTR) NULL, POS_GAD, NULL }; struct Requester vfy_rqst = { NULL, 11,83,299,14, 0,0, &pos_gdgt, NULL, NULL, 0, YLWP, NULL, NULL, NULL, NULL, NULL }; struct NewWindow NewWdw = { 160,11,320,100, BLKP,WHTP, CLOSEWINDOW | GADGETUP | RAWKEY | MOUSEBUTTONS, WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | SMART_REFRESH | NOCAREREFRESH | RMBTRAP | ACTIVATE, NULL, NULL, NULL, NULL, NULL, 0,0,0,0, WBENCHSCREEN }; /*----------------------------- Main program -----------------------------*/ _main() { init(); StartKey(&BookIndexFile); next(); moveptr(&nxt_gdgt,0); while (TRUE) { Wait(MESSAGE); while (msg = (struct IntuiMessage *) GetMsg(wdw->UserPort)) { class = msg->Class; code = msg->Code; qual = msg->Qualifier; iadr = msg->IAddress; ReplyMsg(msg); if (class == GADGETUP) gid = ((struct Gadget *) iadr)->GadgetID; else gid = 0; if (!IGNORE_MSG) { if ((find_flag) && (gid != NAM_GAD)) kill_find(); if (ABORT_MSG) { moveptr(&nxt_gdgt,0); } else { switch (class) { case GADGETUP: dispatch_gad(); break; case RAWKEY: dispatch_key(); break; case CLOSEWINDOW: quit(0); break; } } } } } } /*--------------------------- Function dispatch --------------------------*/ dispatch_gad() { switch (gid) { case FND_GAD: set_find(); break; case ADD_GAD: add(); break; case SAV_GAD: save(); break; case DEL_GAD: delete(); break; case PRV_GAD: prev(); break; case NXT_GAD: next(); break; case NAM_GAD: if (find_flag) find(); else moveptr(&adr_gdgt,1); break; case ADR_GAD: moveptr(&cit_gdgt,1); break; case CIT_GAD: moveptr(&sta_gdgt,1); break; case STA_GAD: moveptr(&zip_gdgt,1); break; case ZIP_GAD: moveptr(&phn_gdgt,1); break; case PHN_GAD: moveptr(¬_gdgt,1); break; case NOT_GAD: moveptr(&nxt_gdgt,0); break; } } dispatch_key() { switch (code) { case FND_KEY: set_find(); break; case SAV_KEY: moveptr(&sav_gdgt,0); save(); break; case ADD_KEY: moveptr(&add_gdgt,0); add(); break; case DEL_KEY: moveptr(&del_gdgt,0); delete(); break; case PRV_KEY: moveptr(&prv_gdgt,0); prev(); break; case NXT_KEY: moveptr(&nxt_gdgt,0); next(); break; case EDT_KEY: moveptr(&nam_gdgt,1); break; } } /*--------------------------- Function handlers --------------------------*/ set_find() { if (UsedRecs(&BookDataFile)) { chkrec(); setmem(&BookRec,sizeof(BookRec),'\0'); showrec(); find_flag = TRUE; moveptr(&nam_gdgt,1); } } find() { if (strlen(BookRec.Name)) { genkey(BookRec.Name,BookKey,sizeof(BKEY)); SearchKey(&BookIndexFile,&BookRecNum,BookKey); if (!BFILE_OK) PrevKey(&BookIndexFile,&BookRecNum,BookKey); readrec(); } else { kill_find(); } moveptr(&fnd_gdgt,0); } kill_find() { BookRec = SaveRec; showrec(); find_flag = FALSE; } save() { BKEY tmpkey; if (UsedRecs(&BookDataFile)) { PutRec(&BookDataFile,BookRecNum,&BookRec); genkey(SaveRec.Name,tmpkey,sizeof(BKEY)); genkey(BookRec.Name,BookKey,sizeof(BKEY)); if (strncmp(tmpkey,BookKey,sizeof(BKEY))) { DeleteKey(&BookIndexFile,&BookRecNum,tmpkey); AddKey(&BookIndexFile,BookRecNum,BookKey); FindKey(&BookIndexFile,&BookRecNum,BookKey); } SaveRec = BookRec; } } add() { if (strlen(BookRec.Name)) { genkey(BookRec.Name,BookKey,sizeof(BKEY)); FindKey(&BookIndexFile,&BookRecNum,BookKey); if (BFILE_OK) BFILE_OK = !verify(&avf_text); if (!BFILE_OK) { AddRec(&BookDataFile,&BookRecNum,&BookRec); genkey(BookRec.Name,BookKey,sizeof(BKEY)); AddKey(&BookIndexFile,BookRecNum,BookKey); FindKey(&BookIndexFile,&BookRecNum,BookKey); showusd(); } SaveRec = BookRec; } } delete() { if (UsedRecs(&BookDataFile)) { if (verify(&dvf_text)) { DeleteKey(&BookIndexFile,&BookRecNum,BookKey); DeleteRec(&BookDataFile,BookRecNum); SearchKey(&BookIndexFile,&BookRecNum,BookKey); if (!BFILE_OK) PrevKey(&BookIndexFile,&BookRecNum,BookKey); showusd(); readrec(); } } } next() { if (UsedRecs(&BookDataFile)) { chkrec(); NextKey(&BookIndexFile,&BookRecNum,BookKey); if (!BFILE_OK) { DisplayBeep(NULL); PrevKey(&BookIndexFile,&BookRecNum,BookKey); } readrec(); } } prev() { if (UsedRecs(&BookDataFile)) { chkrec(); PrevKey(&BookIndexFile,&BookRecNum,BookKey); if (!BFILE_OK) { DisplayBeep(NULL); NextKey(&BookIndexFile,&BookRecNum,BookKey); } readrec(); } } /*---------------------------- Initialization ----------------------------*/ init() { struct Gadget *p; int x1,y1,x2,y2; register int i; if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0))) quit(-1); if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0))) quit(-2); if (!(dev = CreatePort(0,0))) quit(-3); if (!(req = CreateStdIO(dev))) quit(-4); if (OpenDevice("input.device",0,req,0)) quit(-5); req->io_Command = IND_WRITEEVENT; req->io_Flags = 0; req->io_Length = sizeof(struct InputEvent); OpenFile(&BookDataFile,"BLKBOOK.DAT",sizeof(BookRec)); if (BFILE_OK) OpenIndex(&BookIndexFile,"BLKBOOK.IDX",sizeof(BKEY),DUP); if (!BFILE_OK) { MakeFile(&BookDataFile,"BLKBOOK.DAT",sizeof(BookRec)); if (BFILE_OK) MakeIndex(&BookIndexFile,"BLKBOOK.IDX",sizeof(BKEY),DUP); } if (!BFILE_OK) quit(-6); if (!(wdw = (struct Window *) OpenWindow(&NewWdw))) quit(-7); rp = wdw->RPort; if (font = OpenFont(&attr)) SetFont(rp,font); SetWindowTitles(wdw,wdwttl,scrttl); SetAPen(rp,BLKP); RectFill(rp,1,10,318,98); DrawBorder(rp,&sel_brdr,258,87); SetAPen(rp,BLUP); for (i = 1, p = &nam_gdgt; i <= WDW_GAD; i++, p++) { if (p->GadgetID <= STR_GAD) { x1 = p->LeftEdge; y1 = p->TopEdge; x2 = x1 + p->Width - 1; y2 = y1 + p->Height - 1; RectFill(rp,x1,y1,x2,y2); } AddGadget(wdw,p,-1); } SetAPen(rp,WHTP); RefreshGadgets(wdw->FirstGadget,wdw,NULL); showusd(); } /*---------------------------- Misc functions ----------------------------*/ readrec() { GetRec(&BookDataFile,BookRecNum,&BookRec); showrec(); genkey(BookRec.Name,BookKey,sizeof(BKEY)); SaveRec = BookRec; } showrec() { struct StringInfo *p; register int i; for (i = 1, p = &nam_info; i <= STR_GAD; i++, p++) pad(p->Buffer,p->MaxChars); strncpy(Note,BookRec.Note,sizeof(Note)); PrintIText(rp,&nam_disp,0,0); for (i = 1, p = &nam_info; i <= STR_GAD; i++, p++) p->NumChars = trim(p->Buffer); } pad(str,len) char *str; int len; { setmem(&str[strlen(str)],len - strlen(str),' '); str[len - 1] = '\0'; } trim(str) char *str; { register int i; for (i = strlen(str) - 1; (i >= 0) && (str[i] == ' '); str[i--] = '\0'); return(++i); } showusd() { sprintf(used,"%5d",UsedRecs(&BookDataFile)); PrintIText(rp,&usd_text,270,15); } genkey(src,dst,len) char *src; char *dst; int len; { while (len--) (*src) ? (*dst++ = toupper(*src++)) : (*dst++ = ' '); } chkrec() { if (strcmp(BookRec.Name ,SaveRec.Name ) || strcmp(BookRec.Addr ,SaveRec.Addr ) || strcmp(BookRec.City ,SaveRec.City ) || strcmp(BookRec.State,SaveRec.State) || strcmp(BookRec.Zip ,SaveRec.Zip ) || strcmp(BookRec.Phone,SaveRec.Phone) || strcmp(BookRec.Note ,SaveRec.Note )) if (verify(&svf_text)) save(); } moveptr(gad,butn) struct Gadget *gad; int butn; { epos.ie_X = ebut.ie_X = wdw->LeftEdge + gad->LeftEdge + gad->Width - 2; epos.ie_Y = ebut.ie_Y = (wdw->TopEdge + gad->TopEdge + gad->Height - 1) << 1; if (butn) req->io_Data = (APTR) &ebut; else req->io_Data = (APTR) &epos; DoIO(req); } verify(txt) struct IntuiText *txt; { vfy_rqst.ReqText = txt; pos_gdgt.Flags &= ~SELECTED; neg_gdgt.Flags &= ~SELECTED; Request(&vfy_rqst,wdw); Wait(MESSAGE); msg = (struct IntuiMessage *) GetMsg(wdw->UserPort); ReplyMsg(msg); return((int) pos_gdgt.Flags & SELECTED); } /*----------------------------- Termination ------------------------------*/ quit(err) int err; { CloseFile(&BookDataFile); CloseIndex(&BookIndexFile); if (req) { CloseDevice(req); DeleteStdIO(req); } if (dev) DeletePort(dev); if (font) CloseFont(font); if (wdw) CloseWindow(wdw); if (GfxBase) CloseLibrary(GfxBase); if (IntuitionBase) CloseLibrary(IntuitionBase); OpenWorkBench(); exit(err); }