/* TELE.C Written by DavidW Started on 20/11/91 */ #include #include #include #include #include GLREF_D UWORD DatLocked; GLREF_D TEXT *DatUsedPathNamePtr; LOCAL_D TEXT *cmds[]= { "nNew", "oOpen", "mMerge", "sSave as", "kCompress", "xExit", "iInsert", "cCopy", "uUpdate", "aAdd", "dDelete", "rFind previous", "fFind", "gFind next", "jJump to", "zSort", "lDial", "yPrint setup", "pPrint", NULL }; #define FILE_ITEMS 6 #define EDIT_ITEMS 5 #define FIND_ITEMS 3 #define SPECIAL_ITEMS 5 #define ITEMS_BEFORE_FILE 0 #define ITEMS_BEFORE_EDIT FILE_ITEMS #define ITEMS_BEFORE_FIND (ITEMS_BEFORE_EDIT+EDIT_ITEMS) #define ITEMS_BEFORE_SPECIAL (ITEMS_BEFORE_FIND+FIND_ITEMS) LOCAL_D H_MENU_DATA mdata[]= { "File",FILE_ITEMS, "Edit",EDIT_ITEMS, "Find",FIND_ITEMS, "Special",SPECIAL_ITEMS, NULL }; GLDEF_D TEXT ** _cmds=(&cmds[0]); GLDEF_D H_MENU_DATA * _mdata=(&mdata[0]); LOCAL_D UINT MainWid; LOCAL_D struct { UWORD dataStart; UWORD needVersion; UWORD firHeader; UBYTE fir[3]; } ModelHeader= { DbfHeaderLength, 0x100f, (DbfRecordTypeFir<<12)|3, { DbfFieldTypeString, DbfFieldTypeString, DbfFieldTypeWord } }; LOCAL_D TEXT filename[P_FNAMESIZE]; LOCAL_D VOID *dH; LOCAL_D UBYTE dBuf[512]; LOCAL_D UWORD dOff; typedef struct { TEXT nam[20]; TEXT dep[4]; WORD nmb; } ENTRY; LOCAL_D ENTRY clip; LOCAL_D UWORD clipfill=FALSE; LOCAL_D TEXT find[22]={0}; LOCAL_D UWORD PrintState; LOCAL_D TEXT PrintBuf[10]; LOCAL_D UWORD PrintRec; LOCAL_D ENTRY PrintEnt; #define NAME_TLY 4 #define DEPT_TLY 24 #define TELE_TLY 44 #define COUNT_TLY 58 #define TEXT_HEIGHT 18 #define TEXT_ASCENT 16 #define LABEL_TLX 15 #define LABEL_WID 30 #define FIELD_TLX 65 #define FIELD_WID 120 #define COUNT_TLX 105 #define COUNT_WID 75 #define TRN_CALL call(reg_param=>(bx,si),reg_saved=>(cx,dx,di,EPOC_SAVE)) LOCAL_C VOID DisplayPrompt(INT tly,TEXT *buf) { P_RECT box; box.tl.y=tly; box.tl.x=LABEL_TLX; box.br.x=LABEL_TLX+LABEL_WID; box.br.y=tly+TEXT_HEIGHT; gPrintBoxText(&box,TEXT_ASCENT,G_TEXT_ALIGN_CENTRE,0,buf,p_slen(buf)); } LOCAL_C VOID DisplayPrompts(VOID) { DisplayPrompt(NAME_TLY,"Name"); DisplayPrompt(DEPT_TLY,"Dept"); DisplayPrompt(TELE_TLY,"\05"); } LOCAL_C VOID DisplayField(INT tly,TEXT *buf,INT len) { P_RECT box; box.tl.y=tly; box.tl.x=FIELD_TLX; box.br.x=FIELD_TLX+FIELD_WID; box.br.y=tly+TEXT_HEIGHT; gPrintBoxText(&box,TEXT_ASCENT,G_TEXT_ALIGN_LEFT,0,buf,len); } LOCAL_C VOID DisplayCount(TEXT *buf) { P_RECT box; box.tl.x=COUNT_TLX; box.tl.y=COUNT_TLY; box.br.x=COUNT_TLX+COUNT_WID; box.br.y=COUNT_TLY+TEXT_HEIGHT; gPrintBoxText(&box,TEXT_ASCENT,G_TEXT_ALIGN_RIGHT,0,buf,p_slen(buf)); } LOCAL_C VOID BufToEntry(ENTRY *pent) { UBYTE *psrc; INT len; psrc=(&dBuf[dOff+2]); len=(*psrc)+1; p_bcpy(&pent->nam[0],psrc,len); psrc+=len; len=(*psrc)+1; p_bcpy(&pent->dep[0],psrc,len); psrc+=len; pent->nmb=(*(WORD *)psrc); } LOCAL_C VOID CleanEntry(ENTRY *pent) { p_bfil(pent,sizeof(ENTRY),0); } LOCAL_C VOID Display(VOID) { ENTRY ent; UWORD count; TEXT buf[12]; TEXT num[4]; INT len; count=DbfCount(dH); if (count) { p_atos(&buf[0],"%u/%u",DbfSense(dH)+1,count); BufToEntry(&ent); } else { p_scpy(&buf[0],"Empty"); CleanEntry(&ent); } DisplayField(NAME_TLY,&ent.nam[1],ent.nam[0]); DisplayField(DEPT_TLY,&ent.dep[1],ent.dep[0]); if (ent.nmb) len=p_itob(&num[0],ent.nmb); else len=0; DisplayField(TELE_TLY,&num[0],len); DisplayCount(&buf[0]); } LOCAL_C INT EditEntry(ENTRY *pent,TEXT *title) { H_DI_EDIT edname; H_DI_EDIT eddept; LONG lnumb; H_DI_NUMBER numb; if (uOpenDialog(title)) return(-1); edname.len=19; edname.str=(&pent->nam[0]); if (uAddDialogItem(H_DIALOG_EDIT,"Name",&edname)) return(-1); eddept.len=3; eddept.str=(&pent->dep[0]); if (uAddDialogItem(H_DIALOG_EDIT,"Dept",&eddept)) return(-1); lnumb=pent->nmb; numb.value=(&lnumb); numb.low=100; numb.high=999; if (uAddDialogItem(H_DIALOG_NUMBER,"Number",&numb)) return(-1); if (uRunDialog()<=0) return(-1); pent->nmb=lnumb; return(0); } LOCAL_C INT EntryToBuf(ENTRY *pent) { INT len1; INT len2; UBYTE *pb; len1=pent->nam[0]+1; pb=(&dBuf[2]); pb=p_bcpy(pb,&pent->nam[0],len1); len2=pent->dep[0]+1; pb=p_bcpy(pb,&pent->dep[0],len2); *(WORD *)pb=pent->nmb; dOff=0; return(len1+len2+2); } LOCAL_C INT Check(INT val) { TEXT buf[64]; if (val<0 && val!=E_FILE_EOF) { uForceToFront(); DatLocked=TRUE; p_errs(&buf[0],val); wsAlertW(WS_ALERT_CLIENT,&buf[0],"Terminating application",0); p_exit(0); } return(val); } LOCAL_C VOID DoUpdate(INT len) { INT state; state=DbfStateDisabled; Check(DbfUpdate(&state,dH,len)); } LOCAL_C VOID DoAppend(INT len) { Check(DbfAppend(dH,len)); Display(); } LOCAL_C VOID AddRecord(VOID) { ENTRY new; CleanEntry(&new); if (!EditEntry(&new,"Add new record")) DoAppend(EntryToBuf(&new)); } LOCAL_C VOID UpdateRecord(VOID) { ENTRY ent; if (!DbfCount(dH)) { wInfoMsg("No record to update"); return; } BufToEntry(&ent); if (!EditEntry(&ent,"Update record")) { DoUpdate(EntryToBuf(&ent)); Display(); } } LOCAL_C INT Transition( #pragma save,TRN_CALL INT pf(VOID *,UWORD *)) #pragma restore { return(Check(pf(dH,&dOff))); } LOCAL_C VOID DeleteRecord(VOID) { INT state; if (!DbfCount(dH)) { wInfoMsg("No record to delete"); return; } if (uOpenDialog("Delete current record")) return; if (uAddButtonList("No",-'n',"Yes",'y',NULL)) return; if (uRunDialog()!='y') return; state=DbfStateDisabled; if (Check(DbfEraseRead(&state,dH,&dOff))<0) Transition(DbfBackRead); Display(); } LOCAL_C VOID InsertFromClipboard(VOID) { if (!clipfill) { wInfoMsg("No record to insert"); return; } DoAppend(EntryToBuf(&clip)); } LOCAL_C VOID CopyToClipboard(VOID) { if (!DbfCount(dH)) { wInfoMsg("No record to copy"); return; } BufToEntry(&clip); clipfill=TRUE; wInfoMsg("Record copied"); } LOCAL_C INT Search(INT dir) { UINT state; INT len; INT ret; len=find[0]; find[0]='*'; find[len+1]='*'; state=DbfStateDisabled; ret=Check(DbfFindRead(&state,dH,&find[0],len+2, 255|dir|DbfFindCaseIndependent,2,&dOff)); find[0]=len; return(ret); } LOCAL_C INT ResetTo(UINT current) { return(Check(DbfAbsRead(dH,current,&dOff))); } LOCAL_C VOID DoFind(INT dir) { UINT current; current=DbfSense(dH); if (Search(dir)>=0) Display(); else { ResetTo(current); wInfoMsg("Not found"); } } LOCAL_C VOID FindAgain(INT dir1,INT dir2, #pragma save,TRN_CALL INT pf(VOID *,UWORD *)) #pragma restore { UINT current; current=DbfSense(dH); if (Transition(pf)>=0 && Search(dir1)>=0 || Search(dir2)>=0 && DbfSense(dH)!=current) Display(); else { ResetTo(current); wInfoMsg("No more found"); } } LOCAL_C VOID FindNext(VOID) { FindAgain(DbfFindForwards,DbfFindFirst,DbfNextRead); } LOCAL_C VOID FindPrevious(VOID) { FindAgain(DbfFindBackwards,DbfFindLast,DbfBackRead); } LOCAL_C VOID FindRecord(VOID) { H_DI_EDIT edfind; if (uOpenDialog(NULL)) return; edfind.str=(&find[0]); edfind.len=19; if (uAddDialogItem(H_DIALOG_EDIT,"Find",&edfind)) return; if (uAddButtonList("Cancel",W_KEY_ESCAPE,"Find backwards",W_KEY_TAB, "Find forwards",W_KEY_RETURN,NULL)) return; switch (uRunDialog()) { case W_KEY_TAB: DoFind(DbfFindLast); case 0: return; case W_KEY_RETURN: DoFind(DbfFindFirst); } } LOCAL_C VOID DialNumber(VOID) { ENTRY tmp; TEXT buf[4]; if (!DbfCount(dH)) { wInfoMsg("No number to dial"); return; } BufToEntry(&tmp); buf[p_itob(&buf[0],tmp.nmb)]=0; if (hDTMFString(&buf[0])) wInfoMsg("Sound device busy"); } LOCAL_C VOID CompressFile(VOID) { UINT state; if (!hIsDbfCompressible(dH)) wInfoMsg("Cannot compress on Flash"); else { state=DbfStateDisabled; Check(DbfCompress(&state,dH)); wInfoMsg("File compressed"); } } LOCAL_C VOID ChangeName(TEXT *newname) { p_scpy(&filename[0],newname); hSetUpStatusNames(&filename[0]); wsUpdate(WS_UPDATE_NAME); } LOCAL_C VOID DisplayStart(VOID) { Transition(DbfFirstRead); Display(); } LOCAL_C VOID ChangeOverTo(VOID *newdH,TEXT *newname) { DbfClose(dH); dH=newdH; ChangeName(newname); DisplayStart(); } LOCAL_C INT doOpen(VOID **pdH,TEXT *pb,INT flags,DbfHeader *pHead) { INT state; state=DbfStateDisabled; p_scpy((TEXT *)&pHead->fileType[0],"OPLDatabaseFile"); return(uErrorValue(DbfOpen(&state,pdH,pb,flags,pHead,&dBuf[0],512,1))); } LOCAL_C INT TryOpenDbf(TEXT *pb,VOID **pdH) { DbfHeader Header; return(doOpen(pdH,pb,P_FOPEN|P_FUPDATE|P_FRANDOM,&Header)); } LOCAL_C VOID SetupFilename(TEXT *pb) { p_bcpy(pb+1,DatUsedPathNamePtr,*pb=p_slen(DatUsedPathNamePtr)); } LOCAL_C VOID OpenDbf(VOID) { H_DI_FSEL open; TEXT openbuf[P_FNAMESIZE+2]; VOID *newdH; UINT current; current=DbfSense(dH); SetupFilename(open.fname=(&openbuf[0])); open.flags=H_FILE_PICK_SELECTOR|H_FILE_RESTRICT_LIST|H_FILE_SET_DEFEXT; FOREVER { if (uOpenDialog("Open telephone file")) break; if (uAddDialogItem(H_DIALOG_FSEL,"File:",&open)) break; if (uRunDialog()<=0) break; openbuf[1+openbuf[0]]=0; if (!TryOpenDbf(&openbuf[1],&newdH)) { ChangeOverTo(newdH,&openbuf[1]); return; } } ResetTo(current); } LOCAL_C INT TryNewDbf(TEXT *pb,VOID **pdH) { DbfHeader Header; hEnsurePath(pb); Header.createVersion=DbfVersion(); p_bcpy(&Header.dataStart,&ModelHeader,sizeof(ModelHeader)); return(doOpen(pdH,pb,P_FREPLACE|P_FUPDATE|P_FRANDOM,&Header)); } LOCAL_C VOID NewDbf(VOID) { H_DI_FSEL new; TEXT newbuf[P_FNAMESIZE+2]; VOID *newdH; UINT current; current=DbfSense(dH); SetupFilename(new.fname=(&newbuf[0])); new.flags=H_FILE_NEW_EDITOR|H_FILE_SET_DEFEXT; FOREVER { if (uOpenDialog("New telephone file")) break; if (uAddDialogItem(H_DIALOG_FSEL,"File:",&new)) break; if (uRunDialog()<=0) break; newbuf[1+newbuf[0]]=0; if (!TryNewDbf(&newbuf[1],&newdH)) { ChangeOverTo(newdH,&newbuf[1]); return; } } ResetTo(current); } LOCAL_C INT DoMerge(TEXT *pb,INT flags,INT dir) { UINT state; state=DbfStateDisabled; return(uErrorValue(DbfCopyFile(&state,dH,pb,flags,1,dir))); } LOCAL_C VOID MergeDbf(VOID) { H_DI_FSEL merge; TEXT mergebuf[P_FNAMESIZE+2]; UINT current; current=DbfSense(dH); SetupFilename(merge.fname=(&mergebuf[0])); merge.flags=H_FILE_PICK_SELECTOR|H_FILE_RESTRICT_LIST|H_FILE_SET_DEFEXT; FOREVER { if (uOpenDialog("Merge telephone file")) break; if (uAddDialogItem(H_DIALOG_FSEL,"File:",&merge)) break; if (uRunDialog()<=0) break; mergebuf[1+mergebuf[0]]=0; if (!DoMerge(&mergebuf[1],P_FOPEN,DbfCopyToHandle)) { wInfoMsg("File merged"); DisplayStart(); return; } } ResetTo(current); } LOCAL_C VOID DoSave(TEXT *pb,INT usenew) { if (DoMerge(pb,P_FUPDATE|P_FREPLACE,DbfCopyFromHandle)) return; if (usenew) { DbfClose(dH); ChangeName(pb); while (TryOpenDbf(pb,&dH)) ; DisplayStart(); } wInfoMsg("Saved"); } LOCAL_C VOID SaveDbfAs(VOID) { H_DI_FSEL save; TEXT savebuf[P_FNAMESIZE+2]; UWORD usenew; if (uOpenDialog("Save as")) return; SetupFilename(save.fname=(&savebuf[0])); save.flags=H_FILE_NEW_EDITOR|H_FILE_SET_DEFEXT; if (uAddDialogItem(H_DIALOG_FSEL,"File:",&save)) return; usenew=1; if (uAddChoiceList("Use new file",&usenew,"No","Yes",NULL)) return; if (uRunDialog()) { savebuf[1+savebuf[0]]=0; hEnsurePath(&savebuf[1]); DoSave(&savebuf[1],usenew==2); } } LOCAL_C INT ordf(INT r1,INT r2,VOID *base) { UBYTE *table; UBYTE *e1; UBYTE *e2; INT entlen; table=(UBYTE *)base; entlen=(*(UWORD *)table); table+=2; r1=(*(UWORD *)(table+r1*entlen)); r2=(*(UWORD *)(table+r2*entlen)); table+=2; e1=table+r1*entlen; e2=table+r2*entlen; return(p_bcmp(e1+1,*e1,e2+1,*e2)); } LOCAL_C VOID excf(INT r1,INT r2,VOID *base) { UBYTE *table; INT entlen; UWORD *p1; UWORD *p2; UWORD swap; table=(UBYTE *)base; entlen=(*(UWORD *)table); table+=2; p1=(UWORD *)(table+r1*entlen); p2=(UWORD *)(table+r2*entlen); swap=(*p1); *p1=(*p2); *p2=swap; } LOCAL_C INT DoSort(UINT k,INT len) { INT entlen; UBYTE *table; INT i,j; INT thislen; UBYTE *target; UBYTE *source; UWORD moved; INT ret; entlen=len+3; table=p_alloc(2+k*entlen); if (!table) { uErrorString("Insufficient memory"); return(-1); } *(UWORD *)table=entlen; Transition(DbfFirstRead); target=table+2; for (i=0; ilen) thislen=len; *(UWORD *)target=i; *(target+2)=thislen; p_bcpy(target+3,source,thislen); target+=entlen; Transition(DbfNextRead); } if (p_qsort(k,ordf,excf,table)) { uErrorString("Internal sort stack overflow"); ret=(-1); } else { for (i=0; imoved) (*(UWORD *)target)--; target+=entlen; } } ret=0; wInfoMsg("Sorted"); DisplayStart(); } p_free(table); return(ret); } LOCAL_C VOID SortDbf(VOID) { UINT k; LONG len; H_DI_NUMBER num; UINT current; k=DbfCount(dH); if (!k) { wInfoMsg("No records to sort"); return; } current=DbfSense(dH); len=19; num.low=1; num.high=19; num.value=(&len); FOREVER { if (uOpenDialog("Sort file by name")) break; if (uAddDialogItem(H_DIALOG_NUMBER,"Key length",&num)) break; if (uRunDialog()<=0) break; if (DoSort(k,(INT)len)) return; } ResetTo(current); } LOCAL_C VOID JumpTo(VOID) { INT count; LONG curr; H_DI_NUMBER num; count=DbfCount(dH); if (!count) { wInfoMsg("No records to jump to"); return; } if (uOpenDialog(NULL)) return; curr=DbfSense(dH)+1; num.value=(&curr); num.low=1; num.high=count; if (uAddDialogItem(H_DIALOG_NUMBER,"Jump to record",&num)) return; if (uRunDialog()<=0) return; ResetTo((UINT)(curr-1)); Display(); } LOCAL_C INT PrintLine(H_PRINT *pr) { switch (PrintState++) { case 0: if (ResetTo(PrintRec++)<0) return(0); BufToEntry(&PrintEnt); pr->buf=(&PrintEnt.nam[1]); pr->blen=PrintEnt.nam[0]; pr->style|=2; break; case 1: pr->buf=(&PrintEnt.dep[1]); pr->blen=PrintEnt.dep[0]; break; case 2: pr->buf=(&PrintBuf[0]); pr->blen=p_itob(&PrintBuf[0],PrintEnt.nmb); break; case 3: pr->blen=0; PrintState=0; return(TRUE); } pr->flags|=0x8000; return(TRUE); } LOCAL_C VOID DoPrint(VOID) { UINT current; current=DbfSense(dH); PrintState=0; PrintRec=0; hPrint(PrintLine); ResetTo(current); } LOCAL_C VOID ManageCommand(INT index) { switch (index) { case ITEMS_BEFORE_FILE: NewDbf(); break; case ITEMS_BEFORE_FILE+1: OpenDbf(); break; case ITEMS_BEFORE_FILE+2: MergeDbf(); break; case ITEMS_BEFORE_FILE+3: SaveDbfAs(); break; case ITEMS_BEFORE_FILE+4: CompressFile(); break; case ITEMS_BEFORE_FILE+5: p_exit(0); case ITEMS_BEFORE_EDIT: InsertFromClipboard(); break; case ITEMS_BEFORE_EDIT+1: CopyToClipboard(); break; case ITEMS_BEFORE_EDIT+2: UpdateRecord(); break; case ITEMS_BEFORE_EDIT+3: AddRecord(); break; case ITEMS_BEFORE_EDIT+4: DeleteRecord(); break; case ITEMS_BEFORE_FIND: FindPrevious(); break; case ITEMS_BEFORE_FIND+1: FindRecord(); break; case ITEMS_BEFORE_FIND+2: FindNext(); break; case ITEMS_BEFORE_SPECIAL: JumpTo(); break; case ITEMS_BEFORE_SPECIAL+1: SortDbf(); break; case ITEMS_BEFORE_SPECIAL+2: DialNumber(); break; case ITEMS_BEFORE_SPECIAL+3: hPrintSetupDialog(); break; case ITEMS_BEFORE_SPECIAL+4: DoPrint(); } } LOCAL_C INT ObeySystemCommand(INT cmd,TEXT *pb,VOID **pdH) { return((cmd=='O'? TryOpenDbf: TryNewDbf)(pb,pdH)); } LOCAL_C VOID ProcessSystemCommand(VOID) { TEXT buf[P_FNAMESIZE+2]; VOID *newdH; wGetCommand((UBYTE *)&buf[0]); if (buf[0]=='X') p_exit(0); if (!ObeySystemCommand(buf[0],&buf[1],&newdH)) ChangeOverTo(newdH,&buf[1]); } LOCAL_C VOID TryExecuteCommand(INT keycode) { keycode=uLocateCommand(keycode); if (keycode>=0) ManageCommand(keycode); } LOCAL_C VOID MainLoop(VOID) { INT ret; WMSG_KEY key; FOREVER { uGetKey(&key); if (key.keycode&W_EVENT_KEY) { if (key.keycode==CONS_EVENT_COMMAND) ProcessSystemCommand(); } else if (key.keycode&W_SPECIAL_KEY) TryExecuteCommand(key.keycode&(~W_SPECIAL_KEY)); else { switch (key.keycode) { case W_KEY_MENU: if (!(key.modifiers&W_CTRL_MODIFIER)) { ret=uPresentMenus(); if (ret>0) TryExecuteCommand(ret); } break; case W_KEY_LEFT: if (Transition(DbfBackRead)>=0) { Display(); break; } case W_KEY_HOME: Transition(DbfFirstRead); Display(); break; case W_KEY_RIGHT: if (Transition(DbfNextRead)>=0) { Display(); break; } case W_KEY_END: Transition(DbfLastRead); Display(); break; case W_KEY_DELETE_LEFT: DeleteRecord(); break; case W_KEY_TAB: key.modifiers^=W_SHIFT_MODIFIER; case W_KEY_RETURN: if (key.modifiers&W_SHIFT_MODIFIER) FindPrevious(); else FindNext(); break; case W_KEY_HELP: if (key.modifiers&W_PSION_MODIFIER) DialNumber(); } } } } LOCAL_C VOID ReduceScreenSize(VOID) { W_WINDATA wd; wd.extent.tl.x=wd.extent.tl.y=0; wd.extent.width=189; wd.extent.height=80; wSetWindow(MainWid,W_WIN_EXTENT,&wd); if (uErrorValue(wCheckPoint())) p_exit(0); } LOCAL_C VOID CreateGC(VOID) { G_GC gc; INT hgc; gc.style=G_STY_DOUBLE; hgc=gCreateGC(MainWid,G_GC_MASK_STYLE,&gc); if (hgc<0) p_exit(hgc); } LOCAL_C VOID SpecificInit(VOID) { INT command; MainWid=uFindMainWid(); CreateGC(); command=hCrackCommandLine(); if (ObeySystemCommand(command,DatUsedPathNamePtr,&dH)) p_exit(0); ReduceScreenSize(); gBorder(W_BORD_CORNER_4); wsEnable(); DisplayPrompts(); DisplayStart(); } GLDEF_C VOID main(VOID) { uCommonInit(); SpecificInit(); MainLoop(); }