/* @(SH) Funzioni per la manipolazione dei files in direttorio ------------------------------------------------------------------------------ @(VG$) PRIVATE fdir : identificatori per il direttori rdir : identificatori per i tracciati record dispferr : flag che attiva segnalazione errore per campo inesistente dirfl : flags che permettono aperture e chiusure multiple per i direttori recfl : flags che permettono aperture e chiusure multiple per i Tr. record ------------------------------------------------------------------------------ */ #define __CFILES_C /* fv */ #include "cfiles.h" #include "fldtypes.h" #include "lffilesc.h" int hashfun(char *); void setdec(char *, int); char *prefname(void); HIDDEN BOOLEAN pathpread = FALSE; BOOLEAN dispferr = TRUE; int dirfl[2] = {0, 0}, recfl[2] = {0, 0} ; char __ptprf[80] = ""; /* @(#) COpenDir FILES @(ID) Apre il file directory di una ditta. @(FD) @(ISV) name = percorso per il file di direttorio. Versione DOS e XENIX. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegare dettagliatamente il motivo. @(FN) */ void COpenDir(lockmode, dirflg) int lockmode; /* modo di apertura */ int dirflg; /* flag per file comuni */ { PathSt name; if (dirfl[dirflg]++) return; #ifndef DOS if ((excllock(CInsPref(glockname, dirflg), (lockmode == ExclLock)) == -1) && (errno == EACCES)) fatal_box("Locked Directory. Error number : %d ", errno); #endif strcpy(name, CInsPref(directory, dirflg)) ; COpen(&fdir[dirflg], name, sizeof(FileDes), 0, lockmode) ; if (fdir[dirflg].IOR != NoErr) fatal_box("Can't open Directory. Error number : %d ", fdir[dirflg].IOR); } /* @(#) CCloseDir FILES @(ID) Chiude il file di direttorio di una ditta. @(FD) @(ISV) Versione DOS e XENIX. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void CCloseDir(dirflg) int dirflg; /* flag per file comuni */ { #ifndef DOS exclunlock(CInsPref(glockname, dirflg), (fdir[dirflg].LockMode == ExclLock)); #endif if (dirfl[dirflg]) dirfl[dirflg]--; if (!dirfl[dirflg]) CClose(&fdir[dirflg]) ; } /* @(#) COpenFile FILES @(ID) Legge i dati di un archivio dal Direttorio. @(FD) @(ISV) junk = variabile spazzatura per la chiamata della funzione "sleep". s = stringa contenente messaggio di attesa. w = descrittore finestra di attesa. Versione DOS e XENIX. @(FSV) @(IN) Sostituisce l'eventuale simbolo "$" con il prefisso corrente. NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void COpenFile(logicname,filed,lockmode,dirflg) int logicname; /* numero logico file */ FileDes *filed; /* puntatore alla struttura che contiene i dati letti dal direttorio */ int lockmode; /* tipo di lock effettuato sul record */ int dirflg; /* flag per file comuni */ { do { CRead(&fdir[dirflg],(RecType) filed,(long) logicname, lockmode); if (TESTLOCK(fdir[dirflg].IOR)) message_box("Sono in attesa della directory n.ro %d", logicname); } while TESTLOCK(fdir[dirflg].IOR) ; strcpy(filed->SysName, CAddPref(filed->SysName)) ; } ; /* @(#) CCloseFile FILES @(ID) Chiude e Riscrive i dati di un file sul direttorio. @(FD) @(ISV) wd = descrittore di una riga di direttorio. junk = variabile spazzatura per la chiamata della funzione "sleep". s = messaggio di attesa. w = descrittore della finestra di attesa. @(FSV) @(IN) ATTENZIONE : questa funzione aggiorna esclusivamente i campi EOD e Flags . NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void CCloseFile(logicname,filed,dirflg) int logicname; /* numero logico file */ FileDes *filed; /* puntatore al descrittore di un archivio */ int dirflg; /* flag per file comuni */ { FileDes wd; do { CRead(&fdir[dirflg],(RecType) &wd,(long) logicname, Lock); if (TESTLOCK(fdir[dirflg].IOR)) message_box("Sono in attesa della directory n.ro %d", logicname); } while TESTLOCK(fdir[dirflg].IOR); wd.EOD = filed->EOD; wd.Flags = filed->Flags; CWrite(&fdir[dirflg],(RecType) &wd,(long) logicname, UnLock); } /* @($) CGetFile FILES @(ID) Legge i dati relativi ad un archivio nel direttorio. Non sostituisce con il prefisso l'eventuale carattere "$". @(FD) @(ISV) junk = variabile spazzatura per la chiamata della funzione "sleep". s = messaggio di attesa. w = descrittore finestra di attesa. Versione DOS e XENIX. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void CGetFile(logicname,filed,lockmode,dirflg) int logicname; /* numero logico file */ FileDes *filed; /* puntatore al descrittore archivio nel direttorio */ int lockmode; /* tipo di lock sul record */ int dirflg; /* flag per file comuni */ { do { CRead(&fdir[dirflg],(RecType) filed,(long) logicname, lockmode); if (TESTLOCK(fdir[dirflg].IOR)) message_box("Sono in attesa della directory n.ro %d", logicname); } while TESTLOCK(fdir[dirflg].IOR) ; } /* @($) CPutFile FILES @(ID) Chiude il direttorio e Riscrive i dati relativi ad un archivo. Aggiorna tutti i campi. @(FD) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void CPutFile(logicname,filed,dirflg) int logicname; /* numero logico file */ FileDes *filed; /* puntatore al descrittore dell'archivio */ int dirflg; /* flag per file comuni */ { CWrite(&fdir[dirflg],(RecType) filed,(long) logicname, UnLock); } /* @($) zerofdes FILES @(ID) Azzera un descrittore di directory. @(FD) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void zerofdes(d) FileDes *d; /* puntatore al descrittore di un archivio nella direttorio */ { strcpy(d->SysName, ""); d->EOD = 0; d->EOX = 0; d->LenR = 0; d->Flags = 0; strcpy(d->Des, ""); strcpy(d->FCalc, ""); strcpy(d->GenPrompt, ""); } /* @(#) COpenRecDir FILES @(ID) Apre l'Archivio dei Tracciati Record. @(FD) @(ISV) name = nome dell'archivio dei Tracciati Record. Versione DOS e XENIX. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void COpenRecDir(lockmode,dirflg) int lockmode; /* modo di apertura */ int dirflg; /* flag per file comuni */ { PathSt name; if (recfl[dirflg]++) return; strcpy(name, CInsPref(ntrrec, dirflg)) ; COpen(&rdir[dirflg], name, sizeof(RecDes), 0, lockmode) ; if (rdir[dirflg].IOR != NoErr) fatal_box("Can't open record description file. Error number : %d ", rdir[dirflg].IOR); } /* @(#) CCloseRecDir FILES @(ID) Chiude l'Archivio dei Tracciati Record @(FD) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo @(FN) */ void CCloseRecDir(dirflg) int dirflg; /* flag per file comuni */ { if (recfl[dirflg]) recfl[dirflg]--; if (!recfl[dirflg]) CClose(&rdir[dirflg]) ; } /* @(#) CGetRec FILES @(ID) Legge il tracciato record del file "logicname" e lo mette in "recd". @(FD) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void CGetRec(logicname,recd,dirflg) int logicname; /* numero file */ RecDes *recd; /* descrittore record */ int dirflg; /* flag per file comuni */ { CRead(&rdir[dirflg],(RecType) recd,(long) logicname, NoLock); } /* @($) CPutRec FILES @(ID) Aggiorna il file dei Tracciati Record. @(FD) */ void CPutRec(logicname,recd,dirflg) int logicname; /* numero file */ RecDes *recd; /* descrittore record */ int dirflg; /* flag per file comuni */ { CWrite(&rdir[dirflg],(RecType) recd,(long) logicname, NoLock); } /* @($) zerodes FILES @(ID) Azzera il Tracciato Record "r". @(FD) @(ISV) i,j = contatori. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void zerordes(r) RecDes *r; /* descrittore record */ { int i,j ; r->NFields = 0; for (i = 0; i < MaxFields; i++) { strcpy(r->Fd[i].Name, ""); r->Fd[i].TypeF = NullF; r->Fd[i].Len = 0; r->Fd[i].Dec = 0; r->Fd[i].RecOff = 0; } for (i = 0; i < MaxFields; i++) r->SortFd[i] = INVFLD; r->NKeys = 0; for (i = 1; i < MaxKeys; i++) { r->Ky[i].DupKeys = FALSE; r->Ky[i].NkFields = 0; for (j = 0; j < MKFields; j++) r->Ky[i].FieldSeq[j] = INVFLD; for (j = 0; j < MKFields; j++) r->Ky[i].FromCh[j] = INVFLD; for (j = 0; j < MKFields; j++) r->Ky[i].ToCh[j] = INVFLD; } } /* @($) setrdes FILES @(ID) Dato il tracciato record crea la struttura HASH (sortFd) per l'accesso veloce ai campi. @(FD) @(ISV) pos = indirizzo Hash. i = contatore. nf = variabile di lavoro. tmppos = indirizzo hash per l'accesso ai campi. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ word setrdes(r) RecDes *r; /* descrittore record */ { int pos, tmppos, nf, i; for (i = 0; i < MaxFields; i++) r->SortFd[i] = INVFLD; if (r->NFields) { for (i = 0; i < r->NFields; i++) { nf = i; pos = hashfun(r->Fd[nf].Name); while (TRUE) { if (r->SortFd[pos] == INVFLD) { r->SortFd[pos] = (byte) nf; break; } else { if (strcmp(r->Fd[r->SortFd[pos]].Name, r->Fd[nf].Name) <= 0) { pos++; if (pos >= MaxFields) pos = 0; } else { tmppos = r->SortFd[pos]; r->SortFd[pos] = (byte) nf; nf = tmppos; } } } } r->Fd[0].RecOff = 1; for (i = 1; i < r->NFields; i++) r->Fd[i].RecOff = r->Fd[i - 1].RecOff + r->Fd[i - 1].Len; return(r->Fd[r->NFields - 1].RecOff + r->Fd[r->NFields - 1].Len); } return(0); } /* @(SHF) Funzioni per la gestione dei campi dei record @($) setdec FILES @(ID) Data la stringa "s" (contenente un numero) Aggiusta il numero dei decimali in base a "dec". @(FD) @(ISV) s1 = stringa di lavoro. i = contatore. l = lunghezza stringa s1. carry = eventuale riporto approssimazione. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void setdec(s,dec) char *s; /* stringa che deve contenere un numero */ int dec; /* numero di decimali che deve avere il numero */ { char *s1; int i, l, carry; if (LENGTH(s) == 0) strcpy(s, "0"); if ((s1 = strchr(s, ',')) != NULL) *s1 = '.'; s1 = strchr(s, '.'); if ((dec) && (s1 == NULL)) { strcat(s, "."); s1 = strchr(s, '.'); } else if (!dec) { l = LENGTH(s1); /* occhio verificare */ if (s1 != NULL) { carry = (s1[1] >= '5'); *s1 = '\0'; while (carry) { s1--; if (*s1 == '-') break; if (*s1 == '9') { *s1 = '0'; if (s == s1) break; } else { (*s1)++; carry = FALSE; } } if (carry) { for (i = l; i > (*s1 == '-'); i--) s[i] = s[i - 1]; s[(*s1 == '-')] = '1'; } } return; } s1++; l = LENGTH(s1); if (l > dec) { carry = (s1[dec] >= '5'); s1[dec] = '\0'; while (carry) { dec--; if (s1[dec] == '9') { s1[dec] = '0'; if (!dec) break; } else { s1[dec]++; carry = FALSE; } } s1--; while (carry) { s1--; if (*s1 == '-') break; if (*s1 == '9') { *s1 = '0'; if (s == s1) break; } else { (*s1)++; carry = FALSE; } } if (carry) { for (i = l; i > (*s1 == '-'); i--) s[i] = s[i - 1]; s[(*s1 == '-')] = '1'; } } else while (l++ < dec) strcat(s1, "0"); } /* @($) hashfun FILES @(ID) Data la stringa "s" costruisce la chiave Hash. @(FD) @(ISV) l = lunghezza della stringa "s". w[82] = copia di lavoro della stringa "s". temp = variabile di lavoro. pw = puntatore ai caratteri della stringa. Utilizza l'operatore OR Esclusivo. @(FSV) @(IN) Restituisce l'indirizzo HASH. @(FN) */ int hashfun(s) char *s; /* stringa da eleborare */ { int l; char w[82]; unsigned short temp = 0, *pw = (unsigned short *) w; strcpy(w, s); if (ODD(LENGTH(s))) strcat(w, " "); l = LENGTH(s); while ((char *) pw < w + l) { temp ^= *pw; pw++; } l = (short) (temp % (MaxFields - 3)); if (l < 0) l = -l; return(l); } /* @($) findfld FILES @(ID) Ricerca all'interno di un record il campo di nome "s". @(FD) @(ISV) i= variabile di lavoro. startp = variabile di lavoro. cmp = variabile di lavoro. @(FSV) */ int findfld(recd,s) RecDes *recd; /* Descrittore record Tracciato Record */ char *s; /* stringa contenente il nome del campo */ { int i, cmp, startp; i = hashfun(s); startp = i; if (recd->SortFd[i] == INVFLD) return(-1); do { if (!(cmp = strcmp(recd->Fd[recd->SortFd[i]].Name, s))) return((int) (recd->SortFd[i])); else if (cmp > 0) return(-1); else if (++i >= MaxFields) i = 0; if (recd->SortFd[i] == INVFLD) return(-1); } while (i != startp) ; return(-1); } /* @(#) CFieldSize FILES @(ID) Restituisce la lunghezza del campo. @(FD) @(ISV) p = puntatore al campo. @(FSV) */ unsigned int CFieldSize(fieldname,recd) char *fieldname; /* nome del campo */ RecDes *recd; /* descrittore record */ { int p; if ((p = findfld(recd, fieldname)) != -1) return(recd->Fd[p].Len); else return(0); } /* @(#) CFieldDec FILES @(ID) Restituisce il numero di decimali presenti nel campo. @(FD) @(ISV) p = puntatore al campo. @(FSV) */ unsigned int CFieldDec(fieldname,recd) char *fieldname; /* nome del campo */ RecDes *recd; /* descrittore record */ { int p; if ((p = findfld(recd, fieldname)) != -1) return(recd->Fd[p].Dec); else return(0); } /* @(#) CFieldType FILES @(ID) Restituisce un intero rappresentante il tipo del campo. @(FD) @(ISV) p = posizione all'interno del record del campo. @(FSV) */ int CFieldType(fieldname,recd) char *fieldname; /* nome del campo */ RecDes *recd; /* descrittore record */ { int p; if ((p = findfld(recd, fieldname)) != -1) return(recd->Fd[p].TypeF); else return(NullF); } /* @($) getfrmt FILES @(ID) Prepara il il formato per dsprintf per il campo "nf" del tracciato record "recd". @(FD) @(ISV) len = lunghezza del campo. dec = numero di decimali presenti nel campo. @(FSV) */ void getfrmt(recd,nf,frm) RecDes *recd; /* descrittore record */ int nf; /* numero campo */ char *frm; /* stringa in formato per dsprintf */ { int len, dec; strcpy(frm, ""); len = recd->Fd[nf].Len; dec = recd->Fd[nf].Dec; if (recd->Fd[nf].TypeF == IntF) sprintf(frm, "%%%dd", len); else if (recd->Fd[nf].TypeF == Int4F) sprintf(frm, "%%%dld", len); else if (recd->Fd[nf].TypeF == RealF) sprintf(frm, "%%%d.%dt",len, dec); /*cambiare */ else if (recd->Fd[nf].TypeF == WordF) sprintf(frm, "%%%du", len); else if (recd->Fd[nf].TypeF == ZeroF) sprintf(frm, "%%0%dd", len); else if (recd->Fd[nf].TypeF == EZeroF) sprintf(frm, "%%0%dld", len); } /* @(#) CGetField FILES @(ID) Estrae il valore di un campo dal record e lo pone in "fout". Restituisce un eventuale codice errore. @(FD) @(ISV) r = variabile che contiene l'eventuale codice errore. p = variabile per la chiamata di "findfld". s = puntatore alla zona di memoria allocata. frm= stringa per contenere un formato per la dsprintf. @(FSV) @(IN) Si osservi che "fout" deve essere un puntatore a una variabile di tipo coerente con il campo da leggere. @(FN) */ #ifndef FOXPRO int CGetField(fieldname,recd,recin,fout) char *fieldname; /* nome del campo */ RecDes *recd; /* descrittore record */ RecType recin; /* buffer contenente il record */ void *fout; /* contenuto del campo in output */ { int r,p; char *s, frm[30], *wp = (char *) fout; s = malloc(256); p = findfld(recd, fieldname); getfrmt(recd, p, frm); if ((r = CGetFieldBuff(fieldname, recd, recin, s)) != -1) if (recd->Fd[p].TypeF == AlfaF) strcpy((char *) fout, s); else if ((recd->Fd[p].TypeF == IntF) || (recd->Fd[p].TypeF == ZeroF)) { if (LENGTH(s)) *((int *) fout) = CCONVINT(s); else *((int *) fout) = 0; } else if ((recd->Fd[p].TypeF == Int4F) || (recd->Fd[p].TypeF == EZeroF)) { if (LENGTH(s)) *((long *) fout) = CONVLONG(s); else *((long *) fout) = 0L; } else if (recd->Fd[p].TypeF == RealF) atod((DEC *) fout, s); else if (recd->Fd[p].TypeF == DateF) *((TrDate *) fout) = cpackdata(s); else if (recd->Fd[p].TypeF == WordF) { if (LENGTH(s)) *((unsigned *) fout) = (unsigned)CONVLONG(s); else *((unsigned *) fout) = 0; } else if (recd->Fd[p].TypeF == CharF) *wp = *s; else if (recd->Fd[p].TypeF == BoolF) *((BOOLEAN *) fout) = (*s == 'X'); free(s); return(r); } /* @(#) CPutField FILES @(ID) Scrive il contenuto della variabile puntata da "fin" nel campo "fieldname" del record. Restituisce un eventuale codice errore. @(FD) @(ISV) r = variabile che contiene l'eventuale codice errore. p = variabile per la chiamata di "findfld". s = puntatore alla zona di memoria allocata. frm= stringa per contenere un formato per la dsprintf. @(FSV) @(IN) Si osservi che "fin" deve essere un puntatore a una variabile di tipo coerente con il campo da leggere. @(FN) */ int CPutField(fieldname,recd,fin,recout) char *fieldname; /* nome del campo */ RecDes *recd; /* descrittore record */ void *fin; /* puntatore al valore da scrivere */ RecType recout; /* buffer contenetnte il record */ { int p; char s[256], frm[30]; strcpy(s, ""); p = findfld(recd, fieldname); getfrmt(recd, p, frm); if (recd->Fd[p].TypeF == AlfaF) strcpy(s, (char *) fin); else if ((recd->Fd[p].TypeF == IntF) || (recd->Fd[p].TypeF == ZeroF)) sprintf(s, frm, *((int *) fin)); else if ((recd->Fd[p].TypeF == Int4F) || (recd->Fd[p].TypeF == EZeroF)) sprintf(s, frm, *((long *) fin)) ; else if (recd->Fd[p].TypeF == RealF) dsprintf(s, frm, (DEC *) fin); else if (recd->Fd[p].TypeF == DateF) ceditdata(*((TrDate *) fin), s); else if (recd->Fd[p].TypeF == WordF) sprintf(s, frm, *((unsigned *) fin)) ; else if (recd->Fd[p].TypeF == CharF) { s[0] = *((char *) fin); s[1] = '\0'; } else if (recd->Fd[p].TypeF == BoolF) { s[0] = *((BOOLEAN*) fin) ? 'X' : ' '; s[1] = '\0'; } return CPutFieldBuff(fieldname, recd, s, recout); } #endif /* FOXPRO */ /* @(#) CGetFieldBuff FILES @(ID) Estrae il valore di un campo dal record e lo pone nella stringa "s". Restituisce un eventuale codice errore. @(FD) @(ISV) p = puntatore al campo. i = contatore. Off = offest in byte all'interno del record per il campo in oggetto. len = lunghezza campo. s1 = stringa di lavoro. d = data in formato stringa. @(FSV) @(IN) Utilizzato per il Data Entry. @(FN) */ int CGetFieldBuff(fieldname,recd,recin,s) char *fieldname; /* nome del campo */ RecDes *recd; /* descrittore record */ RecType recin; /* buffer contenente il record */ char *s; /* stringa per l'output */ { int p, i; unsigned int off; byte len; char *s1; TrDate d; if ((p = findfld(recd, fieldname)) != -1) { off = recd->Fd[p].RecOff; len = recd->Fd[p].Len; if ((recd->Fd[p].TypeF != AlfaF) && (recd->Fd[p].TypeF != DateF) && (recd->Fd[p].TypeF != ZeroF) && (recd->Fd[p].TypeF != EZeroF)) { while ((recin[off] == ' ') && (len)) { off++; len--; } if ((recd->Fd[p].TypeF != RealF) && (recd->Fd[p].TypeF != CharF)) { while ((recin[off] == '0') && (len)) { off++; len--; } } } else if ((recd->Fd[p].TypeF == ZeroF) || (recd->Fd[p].TypeF == EZeroF)) { int i = 0, pos = 0; while (i < len) { if (recin[off + i] != '0') break; i++; pos = i; } if (pos == len) { off += len; len = 0; } } if (len) { s1 = recin + off; for (i = 0; i < len; i++) s[i] = s1[i]; s[len] = '\0'; while ((len) && (s[len - 1] == ' ')) s[--len] = '\0'; } else strcpy(s, ""); if ((recd->Fd[p].TypeF == DateF)) { if (LENGTH(s)) d = atol(s); /* sscanf(s, "%ld", &d); */ else d = 0 ; ceditdata(d, s); } if ((recd->Fd[p].TypeF == RealF)) if ((s1 = strchr(s, ',')) != NULL) *s1 = '.'; return(0); } else { strcpy(s, ""); return(-1); } } /* @(#) CPutFieldBuff FILES @(ID) Scrive il contenuto della stringa "s" nel campo "fieldname" del record. Restituisce un eventuale codice errore. @(FD) @(ISV) p = puntatore al campo. i = contatore. l = variabile di lavoro. off = offest in byte all'interno del record per il campo in oggetto. len = lunghezza campo. s1,s2 = stringa di lavoro. d = data in formato stringa. @(FSV) @(IN) Utilizzato per il Data Entry @(FN) */ int CPutFieldBuff(fieldname,recd,s,recout) char *fieldname; /* nome del campo */ RecDes *recd; /* descrittore record */ char *s; /* stringa contenente il valore da scrivere nel campo */ RecType recout; /* buffer contenente il record */ { int p, off, len, l, i; char *s1; char *s2; TrDate d; s2 = malloc(256); strcpy(s2, s); if ((p = findfld(recd, fieldname)) != -1) { off = recd->Fd[p].RecOff; len = recd->Fd[p].Len; if (recd->Fd[p].TypeF == DateF) { d = cpackdata(s2); sprintf(s2,"%06ld", d); } if (recd->Fd[p].TypeF == RealF) setdec(s2, recd->Fd[p].Dec); l = LENGTH(s2); if (l > len) { free(s2); return(-1); } s1 = recout + off ; for (i = 0; i < l ; i++) s1[i] = s2[i] ; if ((recd->Fd[p].TypeF == IntF) || (recd->Fd[p].TypeF == Int4F) || (recd->Fd[p].TypeF == WordF) || (recd->Fd[p].TypeF == RealF) || (recd->Fd[p].TypeF == ZeroF) || (recd->Fd[p].TypeF == EZeroF)) { char c; if ((recd->Fd[p].TypeF == ZeroF) || (recd->Fd[p].TypeF == EZeroF)) c = '0'; else c = ' '; if (l == 0) s1[l++] = '0'; while (l < len) { for (i = l; i > 0; i--) s1[i] = s1[i - 1]; s1[0] = c; l++; } } else while (l < len) s1[l++] = ' '; free(s2); return(0); } else { strcpy(s, ""); free(s2); return(-1); } } /* @(#) CZeroField FILES @(ID) Azzera un campo. @(FD) @(ISV) p = puntatore al campo. s = stringa messaggio. @(FSV) */ int CZeroField(fieldname,recd,recout) char *fieldname; /* nonme del campo */ RecDes *recd; /* descrittore record */ RecType recout; /* buffer contenente il record */ { int p; if ((p = findfld(recd, fieldname)) != -1) { if (recd->Fd[p].TypeF == DateF) memset(recout + recd->Fd[p].RecOff, '0', recd->Fd[p].Len); else { memset(recout + recd->Fd[p].RecOff, Blank, recd->Fd[p].Len); if ((recd->Fd[p].TypeF == IntF) || (recd->Fd[p].TypeF == Int4F) || (recd->Fd[p].TypeF == WordF)) { *(recout + recd->Fd[p].RecOff + recd->Fd[p].Len - 1) = '0'; } else if (recd->Fd[p].TypeF == RealF) { if (recd->Fd[p].Dec) { memset(recout + recd->Fd[p].RecOff + recd->Fd[p].Len - recd->Fd[p].Dec - 2, '0', recd->Fd[p].Dec + 2); *(recout + recd->Fd[p].RecOff + recd->Fd[p].Len - recd->Fd[p].Dec - 1) = '.'; } else *(recout + recd->Fd[p].RecOff + recd->Fd[p].Len - 1) = '0'; } return(NoErr); } } else return(-1); return(NoErr); } /* @(#) CZeroRec FILES @(ID) Azzera tutto il record. @(FD) @(ISV) i = contatore. junk = variabile spazzatura per la chiamata di CZeroField. @(FSV) */ void CZeroRec(recd,recout) RecDes *recd; /* descrittore record */ RecType recout; /* buffer contenente il record */ { int i, junk; IRecallRec(recout) ; for (i = 0; i < recd->NFields; i++) junk = CZeroField(recd->Fd[i].Name, recd, recout); } /* @($) CBuildKey FILES @(ID) Costruisce la chiave corrispondente al numero chiave. @(FD) @(ISV) i = contatore. nf = numero campi che compongono la chiave. len = lunghezza del campo. off = offest in byte all'interno del record per il campo in oggetto. l = variabile di lavoro. up = variabile di lavoro per rendere maiuscola la stringa. wd = variabile per la data. s1 = stringa di lavoro. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ int CBuildKey(recd,numkey,recin,key) RecDes *recd; /* descrittore record */ int numkey; /* numero chiave */ RecType recin; /* buffer contenente il record */ char *key; /* valore della chiave */ { int i, nf, l = 0, len, off; TrDate wd ; char s1[10]; BOOLEAN upp = FALSE; strcpy(key, ""); if (numkey-- <= recd->NKeys) { for (i = 0; i < recd->Ky[numkey].NkFields; i++) { if ((upp = (recd->Ky[numkey].FieldSeq[i] > MaxFields)) == TRUE) nf = recd->Ky[numkey].FieldSeq[i] - MaxFields; else nf = recd->Ky[numkey].FieldSeq[i]; if (recd->Ky[numkey].FromCh[i] == INVFLD) { off = recd->Fd[nf].RecOff; len = recd->Fd[nf].Len; } else { if (recd->Fd[nf].TypeF == DateF) { off = recd->Fd[nf].RecOff; len = recd->Fd[nf].Len; strncpy(s1, (recin + off), len); s1[len] = '\0'; wd = 0; for(len = 0; len < LENGTH(s1); len++) if (isdigit(s1[len])) wd = (wd * 10) + (s1[len] - '0'); ceditdata(wd, s1); s1[2] = s1[3]; s1[3] = s1[4]; s1[4] = s1[6]; s1[5] = s1[7]; s1[6] = '\0'; off = recd->Ky[numkey].FromCh[i]; len = recd->Ky[numkey].ToCh[i] - recd->Ky[numkey].FromCh[i] + 1; } else { off = recd->Fd[nf].RecOff + recd->Ky[numkey].FromCh[i]; len = recd->Ky[numkey].ToCh[i] - recd->Ky[numkey].FromCh[i] + 1; } } if ((l + len) > 80) { strcpy(key, ""); return(BTrKeyLenErr); } if ((recd->Fd[nf].TypeF == DateF) && (recd->Ky[numkey].FromCh[i] != INVFLD)) strncpy((key + l), &s1[off], len); else { strncpy((key + l), (recin + off), len); if (recin[off] == '\0') memset(key + l, ' ', len); else if ((recd->Fd[nf].TypeF == IntF) || (recd->Fd[nf].TypeF == Int4F) || (recd->Fd[nf].TypeF == WordF)) { int w = l, j = l + len; while (w < j && key[w] == ' ') w++; while (w < j && key[w] == '0') key[w++] = ' '; } } l += len; } key[l] = '\0'; crtrim(key); if (upp) CUpString(key) ; return(NoErr); } return(BTrPathErr); } /* @($) CCalcLenKey FILES @(ID) Ritorna la lunghezza della chiave. @(FD) @(ISV) nf = numero campi chiave. i = contatore. l = variabile di lavoro. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ int CCalcLenKey(recd,numkey) RecDes *recd; /* descrittore record */ int numkey; /* numero della chiave */ { register int l = 0, i, nf; if (numkey-- <= recd->NKeys) { for (i = 0; i < recd->Ky[numkey].NkFields; i++) { if (recd->Ky[numkey].FieldSeq[i] > MaxFields) nf = (int) recd->Ky[numkey].FieldSeq[i] - MaxFields; else nf = (int) recd->Ky[numkey].FieldSeq[i]; if (recd->Ky[numkey].FromCh[i] == INVFLD) l += (int) recd->Fd[nf].Len; else l += (int) (recd->Ky[numkey].ToCh[i] - recd->Ky[numkey].FromCh[i] + 1); } return(l); } return(-1); } /* @($) prefname FILES @(ID) Restituisce il nome del file che contiene il prefisso corrente. @(FD) @(ISV) s,s1 = stringhe di lavoro. Versione DOS e XENIX. @(FSV) */ char *prefname() { static PathSt s; #ifdef DOS char *s1 = getenv("PREFPATH"); if (s1 == NULL) s1 = "prefix.txt"; strcpy(s, s1); #else sprintf(s, "prefix.%-d", getuid()); #endif return(s) ; } /* @(#) CGetPref FILES @(ID) Legge dal file prefisso il prefisso dati corrente. @(FD) @(ISV) f = puntatore al file. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ char *CGetPref() { const char* p = prefname(); FILE *f = fopen(p, "r"); if (f == NULL) { strcpy(cprefix, ""); } else { if (fgets(cprefix, 42, f) != NULL) { const int len = LENGTH(cprefix)-1; if (len >= 0 && cprefix[len] <= ' ') cprefix[len] = '\0'; } else *cprefix = '\0'; fclose(f); } if (!pathpread) { const char* p = "pathpref.ini"; FILE* f = fopen(p, "r"); pathpread = TRUE; if (f != NULL) { if (fgets(__ptprf, 42, f) != NULL) { const int len = LENGTH(__ptprf)-1; if (len >= 0 && __ptprf[len] <= ' ') { __ptprf[len] = '\0'; if (len > 0) strcat(__ptprf, "/"); } } else *__ptprf = '\0'; fclose(f); } } if (*__ptprf) { char ws[200]; sprintf(ws, "%s%s", __ptprf, cprefix); strcpy(cprefix, ws); } return(cprefix); } /* @($) CPutPref FILES @(ID) Aggiorna sul file prefisso il prefisso dati corrente. @(FD) @(ISV) f = puntatore a file. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ void CPutPref(pref) char *pref; /* stringa contenente il nuovo prefisso */ { FILE *f; const int l = strlen(__ptprf); if (l && strncmp(pref, __ptprf, l) == 0) pref += l + 1; if ((f = fopen(prefname(), "w")) == NULL) fatal_box("Put prefix. Error number : %d ", errno); fprintf(f, "%s\n", pref); fclose(f); strcpy(cprefix, pref); } /* @($) CAddPref FILES @(ID) Cerca il carattere "$" nel nome file e lo sostituisce con il prefisso corrente. @(FD) @(ISV) s = stringa che contiene il nome. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ char *CAddPref(name) char *name; /* nome file */ { static PathSt s; if (*name == '$') { name++; return(CInsPref(name, NORDIR)) ; } else if (*name == '%') { name++; return(CInsPref(name, COMDIR)) ; } else { strcpy(s, name); return(s); } } /* @($) CInsPref FILES @(ID) Aggiunge (a sinistra) il prefisso corrente. @(FD) @(ISV) s = stringa di lavoro. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. @(FN) */ char *CInsPref(name,dirflg) char *name; /* nome del file cui aggiungere il prefisso */ int dirflg; /* flag per file comuni */ { static PathSt s; if (dirflg == NORDIR) { if (LENGTH(cprefix) == 0) sprintf(s,"%s", name); else sprintf(s,"%s%c%s",cprefix, DIRSEP, name); } else sprintf(s,"%scom%c%s", __ptprf, DIRSEP, name); return(s); } /* @(#) CGetIdxName FILES @(ID) Dato un nome file costruisce il nome del file indice corrispondente. @(FD) @(ISV) fdst,s1,s2 = stringhe di lavoro. @(FSV) @(IN) NON UTILIZZARE !!. Se si utilizza spiegarne dettagliatamente il motivo. L' estensione dei file indice e' ndx; e' quindi vietato utilizzare un nome di file che abbia tale estensione. L' estensione dei file dati e' dta. @(FN) */ char *CGetIdxName(s) char *s; /* stringa contenente il nome file */ { static PathSt fdst; char *s1, *s2; strcpy(fdst, s) ; s1 = strrchr(fdst,DIRSEP) ; if (s1 == NULL) s1 = fdst; s2 = strchr(s1,'.') ; if (s2 != NULL) s2[0] = '\0' ; s1 = strcat(fdst, ".ndx") ; return(fdst) ; }