ftp.nice.ch/pub/next/unix/communication/ft_bbs.1.0.s.tar.gz#/ft_bbs-1.0/tliste.c

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.