This is tliste.c in view mode; [Download] [Up]
/* $Id: tliste.c,v 1.2 1995/12/19 19:30:47 eilts Exp eilts $ */ #include "bbs.h" /* Funktionen zum Verwalten eines unbegrenzten Stringarrays, Index k. Das Array besteht aus einer Liste von kleinen Arrays der Laenge blocklen. Ist copy FALSE, werden nur Zeiger auf die Strings gespeichert/zurueckgegeben, bei copy TRUE wird der String gespeichert/geliefert. Die Parameter blocklen und copy muessen fuer je eine Liste konstant bleiben. Vor dem ersten Aufruf muss * tl auf Null initialisiert sein. */ int addstrtoliste(tlistetyp **tl, const boolean copy, const int k, const int blocklen, char *str, const confrecordtyp *confrecord) /* Fuegt Zeiger auf str in Liste *tl, Index k, ein. Ist copy TRUE, wird zusaetzlich der String str abgespeichert. Rueckgabewert ist 0, wenn ok, sonnst -1 */ { int blocknr, blockidx, nr, s; boolean neu = FALSE; tlistetyp *tlp; blocknr = k / blocklen; blockidx = k - blocknr * blocklen; if (*tl == (tlistetyp *)0) { if ((*tl=malloc(sizeof(tlistetyp))) == NULL) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","addstrtoliste","malloc: %m"); return(-1); } if (((*tl)->tp=malloc((blocklen*sizeof(char *)))) == NULL) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","addstrtoliste","malloc: %m"); exit(-1); } for (s=0; s<blocklen; s++) (*tl)->tp[s] = (char *)0; (*tl)->nr = 0; (*tl)->prec = (tlistetyp *)0; (*tl)->next = (tlistetyp *)0; } while ((*tl)->nr > blocknr && (*tl)->prec != (tlistetyp *)0) { *tl = (*tl)->prec; } while ((*tl)->nr < blocknr && (*tl)->next != (tlistetyp *)0) { *tl = (*tl)->next; } while ((*tl)->nr < blocknr) { neu = TRUE; if (((*tl)->next=malloc(sizeof(tlistetyp))) == NULL) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","addstrtoliste","malloc: %m"); return(-1); } nr = (*tl)->nr + 1; tlp = (*tl)->next; tlp->prec = *tl; *tl = (*tl)->next; (*tl)->nr = nr; (*tl)->next = (tlistetyp *)0; if (((*tl)->tp=malloc((blocklen*sizeof(char *)))) == NULL) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","addstrtoliste","malloc: %m"); exit(-1); } for (s=0; s<blocklen; s++) (*tl)->tp[s] = (char *)0; } if ((*tl)->nr == blocknr) { if (copy) { if (neu) free((*tl)->tp[blockidx]); if (((*tl)->tp[blockidx]=malloc((strlen(str)+1)*sizeof(char)))==NULL) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","addstrtoliste", "malloc: %m"); exit(-1); } strcpy((*tl)->tp[blockidx],str); } else { (*tl)->tp[blockidx] = str; } } else { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","addstrtoliste", "step too large"); return(-1); } return(0); } int readliste(tlistetyp **tl, const boolean copy, const int k, const int blocklen, char **str, const confrecordtyp *confrecord) /* Liefert Zeiger str Index k in str zurueck. Ist copy TRUE, wird zusaetzlich der String nach str kopiert. Rueckgabewert ist 0, wenn ok, sonnst -1 */ { int blocknr, blockidx; if (*tl == (tlistetyp *)0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","readliste", "tl points to zero"); return(-1); } if (k < 0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","readliste","Index < 0"); return(-1); } blocknr = k / blocklen; blockidx = k - blocknr * blocklen; while ((*tl)->nr<blocknr && (*tl)->next!=(tlistetyp *)0) { *tl = (*tl)->next; } while ((*tl)->nr>blocknr && (*tl)->prec!=(tlistetyp *)0) { *tl = (*tl)->prec; } if ((*tl)->nr != blocknr) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","readliste","indexoverflow"); return(-1); } if ((*tl)->tp[blockidx] == (char *)0) { errormsg(E_LOGFILE|E_USER,confrecord,"bbs","readliste", "string point to 0"); return(-1); } if (copy) { strcpy(*str,(*tl)->tp[blockidx]); } else { *str = (*tl)->tp[blockidx]; } return(0); } int removeliste(tlistetyp **tl, const boolean copy, const int blocklen) /* Loescht die Liste tl. */ { int k; if (*tl == (tlistetyp *)0) return(0); while((*tl)->prec != (tlistetyp *)0) *tl = (*tl)->prec; while((*tl)->next != (tlistetyp *)0) { if (copy) { for (k=0; k<blocklen; k++) { if ((*tl)->tp[k] != (char *)0) free((*tl)->tp[k]); } } free((*tl)->tp); *tl = (*tl)->next; free((*tl)->prec); } if (copy) { for (k=0; k<blocklen; k++) { if ((*tl)->tp[k] != (char *)0) free((*tl)->tp[k]); } } free((*tl)->tp); free(*tl); *tl = (tlistetyp *)0; return(0); } int inserttoliste(tlistetyp **tl, const boolean copy, const int k, int *anz, const int blocklen, char *str, const confrecordtyp *confrecord) { int n; char *sp; for (n=*anz; n>k; n--) { readliste(tl,FALSE,n-1,blocklen,&sp,confrecord); addstrtoliste(tl,FALSE,n,blocklen,sp,confrecord); } (*anz)++; return addstrtoliste(tl,copy,k,blocklen,str,confrecord); } int delfromliste(tlistetyp **tl, const boolean copy, const int k, int *anz, const int blocklen, const confrecordtyp *confrecord) { int n; char *sp; if (copy) { readliste(tl,FALSE,k,blocklen,&sp,confrecord); free(sp); } for (n=k; n<*anz-1; n++) { readliste(tl,FALSE,n+1,blocklen,&sp,confrecord); addstrtoliste(tl,FALSE,n,blocklen,sp,confrecord); } addstrtoliste(tl,FALSE,*anz-1,blocklen,(char *)0,confrecord); (*anz)--; n = *anz % blocklen; if (n == 0) { free((*tl)->next); (*tl)->next = (tlistetyp *)0; } return 0; } void sortliste(tlistetyp *tl, const int blocklen, const int anz, const confrecordtyp *confrecord) /* Sortiert die Liste tl. */ { if (anz > 1) sort_liste(tl, blocklen, 0, anz-1, strcmp, confrecord); return; } void sort_liste(tlistetyp *tl, const int blocklen, const int k1, const int k2, int (*cmpfkt)(const char *s1, const char *s2), const confrecordtyp *confrecord) { int i, j; char *x, *xi, *xj; i = k1; j = k2; if (readliste(&tl,FALSE,(k1+k2)/2,blocklen,&x,confrecord) < 0) return; do { do { readliste(&tl,FALSE,i,blocklen,&xi,confrecord); i++; } while (cmpfkt(xi,x) < 0 && i <= k2); i--; do { readliste(&tl,FALSE,j,blocklen,&xj,confrecord); j--; } while (cmpfkt(xj,x) > 0 && j >= k1); j++; if (i <= j) { addstrtoliste(&tl,FALSE,i,blocklen,xj,confrecord); addstrtoliste(&tl,FALSE,j,blocklen,xi,confrecord); i++; j--; } } while (i <= j); if (k1 < j) sort_liste(tl,blocklen,k1,j,cmpfkt,confrecord); if (i < k2) sort_liste(tl,blocklen,i,k2,cmpfkt,confrecord); return; } char tlpager(tlistetyp *tliste, const int anz, const char *header, const char *helpcontext, const confrecordtyp *confrecord) /* Ein Pager fuer Texte, die zeilenweise in einer tliste organisiert sind. */ { int kopfzeilen, lines, zstep, offset, ypos, kmax, k, n, lang; char prompt[S_STRLEN+1], *sp, key; char cset[] = {SPACE_KEY,BACKSPACE_KEY,DELETE_KEY,'Q','\0'}; lang = confrecord->userrecord.lang; kopfzeilen = 2; lines = confrecord->userrecord.lines - kopfzeilen -1; zstep = lines - 2; offset = 0; move(0,0); clear(); addstr(header); do { move(kopfzeilen,0); clrtobot(); kmax = offset+lines > anz ? anz : offset+lines; for (k=offset,n=0; k<kmax; k++,n++) { ypos = kopfzeilen + k - offset; readliste(&tliste,FALSE,k,TL_BLOCKLEN,&sp,confrecord); move(ypos,2); addstr(sp); } if (anz > lines) { if (offset+lines < anz) { if (offset == 0) { strcpy(prompt,msg("tlpager",1,lang)); } else { sprintf(prompt,msg("tlpager",2,lang),offset); } } else { strcpy(prompt,msg("tlpager",0,lang)); } } else { if (anz > 0) { strcpy(prompt,msg("tlpager",3,lang)); } else { strcpy(prompt,msg("tlpager",4,lang)); } } key = getkeyonprompt(prompt,cset,TRUE,FALSE,helpcontext,confrecord); if (pagerstep(key) < 0) { offset -= zstep; } else if (pagerstep(key) > 0) { offset += zstep; } if (offset > anz-lines) offset = anz-lines; if (offset < 0) offset = 0; } while (pagerquit(key) == 0); return(key); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.