/* 
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/
#ident "$Header: cat_misc.c 1.2 90/05/16 $@(#)cat_misc.c	1.1 89/12/06 "
#include <stdio.h>
#include <nl_types.h>
#include "nl_type2.h"

extern char *gettxt();
/*
 * Add a set in the set list
 */
add_set(set_nr)
  int set_nr;
{
  struct cat_set *ptr, *ptr2, *new;
  
  if (set_nr > NL_SETMAX || set_nr <= 0){
    fprintf(stderr, gettxt("gencat:16","Invalid set number %d -- Ignored\n"));
    return;
  }

  ptr2 = ptr = sets;
  
  /*
   * Scan list to find set or bigger
   */
  while (ptr != 0){
    if (ptr->set_nr == set_nr){
      /*
       * Found set in the list
       */
      curset = set_nr;
      return;
    }
    if (ptr->set_nr > set_nr)
      /*
       * Found a bigger set number
       */
      break;
    ptr2 = ptr;
    ptr = ptr->set_next;
  }
  
  /*
   * Insert new set in list, before ptr;
   */
  if ((new = (struct cat_set *)malloc(sizeof(struct cat_set))) == 0){
    fprintf(gettxt("gencat:17","Out of memory (cat_misc.c (1))\n"));
    fatal();
  }
  new->set_nr = set_nr;
  new->set_msg_nr = 0;
  new->set_next = ptr;
  new->set_msg = 0;
  
  if (ptr2 == ptr)
    sets = new;
  else
    ptr2->set_next = new;
  curset = set_nr;
} 

/*
 * Delete a set
 */
del_set(set_nr)
  int set_nr;
{
  struct cat_set *ptr, *ptr2, *new;
  bool found;
  
  if (set_nr > NL_SETMAX || set_nr <= 0){
    fprintf(stderr, gettxt("gencat:18","Invalid set number %d -- Ignored\n"));
    return;
  }

  ptr2 = ptr = sets;
  found = FALSE;
  
  /*
   * Scan list to find set or bigger
   */
  while (ptr != 0){
    if (ptr->set_nr == set_nr){
      /*
       * Found set in the list
       */
      found = TRUE;
      break;
    }
    if (ptr->set_nr > set_nr)
      /*
       * Found a bigger set number
       */
      break;
    ptr2 = ptr;
    ptr = ptr->set_next;
  }
  if (!found){
    fprintf(stderr, gettxt("gencat:19","del_set : Set not found %d -- Ignored\n"), set_nr);
    return;
  }
  
  /*
   * Delete message queue
   */
  del_all_msgs(ptr->set_msg);
  
  /*
   * Delete from queue
   */
  if (ptr2 == ptr)
    sets = ptr->set_next;
  else
    ptr2->set_next = ptr->set_next;
  free((char *)ptr);

  if (set_nr == curset)
    curset = 0;
}

/*
 * Delete a message
 */
del_msg(set_nr, msg_nr)
  int set_nr;
  int msg_nr;
{
  struct cat_msg *ptr, *ptr2, *new;
  struct cat_set *set_ptr;
  bool found;
    
  /*
   * Get a pointer to the set
   */
  if ((set_ptr = get_set_ptr(set_nr)) == 0){
    fprintf(stderr, gettxt("gencat:20","Invalid set number %d -- Ignored\n"), set_nr);
    return;
  }

  if (msg_nr > NL_MSGMAX || msg_nr <= 0){
    fprintf(stderr, gettxt("gencat:21","Invalid message number %d -- Ignored\n"), msg_nr);
    return;
  }

  ptr2 = ptr = set_ptr->set_msg;
  found = FALSE;
  
  /*
   * Scan list to find msg or bigger
   */
  while (ptr != 0){
    if (ptr->msg_nr == msg_nr){
      /*
       * Found set in the list
       */
      found = TRUE;
      break;
    }
    if (ptr->msg_nr > msg_nr)
      /*
       * Found a bigger msg number
       */
      break;
    ptr2 = ptr;
    ptr = ptr->msg_next;
  }
  if (!found){
    fprintf(stderr, gettxt("gencat:22","del_msg : msg not found %d -- Ignored\n"), msg_nr);
    return;
  }
  
  /*
   * Delete from queue
   */
  if (ptr2 == ptr)
    set_ptr->set_msg = ptr->msg_next;
  else
    ptr2->msg_next = ptr->msg_next;
  free((char *)ptr);
}

/*
 * Add a message in a set.
 */
add_msg(set_nr, msg_nr, msg_len, msg_buf)
  int set_nr, msg_nr, msg_len;
  char *msg_buf;
{
  struct cat_set *set_ptr;
  struct cat_msg *ptr, *ptr2, *new;
  bool replace;
  
  /*
   * Get a pointer to the set
   */
  if ((set_ptr = get_set_ptr(set_nr)) == 0){
    fprintf(stderr, gettxt("gencat:23","Invalid set number %d -- Ignored\n"), set_nr);
    return;
  }

  if (msg_nr > NL_MSGMAX || msg_nr <= 0){
    fprintf(stderr, gettxt("gencat:24","Invalid message number %d -- Ignored\n"), msg_nr);
    return;
  }
  
  if (msg_len > NL_TEXTMAX + 1 || msg_len < 0){
    fprintf(stderr, gettxt("gencat:25","Invalid message length %d -- Ignored\n"), msg_len);
    return;
  }
  
  /*
   * Scan message queue
   */
  ptr = ptr2 = set_ptr->set_msg;
  replace = FALSE;
  
  while (ptr != 0){
    if (ptr->msg_nr == msg_nr){
      new = ptr;
      replace = TRUE;
      break;
    }
    if (ptr->msg_nr > msg_nr)
      break;
    ptr2 = ptr;
    ptr = ptr->msg_next;
  }
  
  /*
   * Not a replacement : alloc msg header
   */
  if (!replace){
    if ((new = (struct cat_msg *)malloc(sizeof(struct cat_msg))) == 0){
      fprintf(stderr, gettxt("gencat:26","Out of memory (cat_misc.c (2))\n"));
      fatal();
    }
    new->msg_nr = msg_nr;
    new->msg_next = ptr;

    if (ptr == ptr2)
      set_ptr->set_msg = new;
    else
      ptr2->msg_next = new;
  }
  /*
   * Put message in the temp file and keep offset
   */
  new->msg_off = ftell(tempfile);
  new->msg_len = msg_len;

  if (fwrite(msg_buf, 1, msg_len, tempfile) != msg_len){
    fprintf(stderr, gettxt("gencat:27","add_msg : Write error in temp file\n"));
    fatal();
  }
}

/*
 * Delete all messages from a queue
 */
del_all_msgs(ptr)
  struct cat_msg *ptr;
{
  struct cat_msg *ptr2;
  
  while (ptr != 0){
    ptr2 = ptr->msg_next;
    free((char *)ptr);
    ptr = ptr2;
  }
}
/*
 * Return a pointer to a set
 */
struct cat_set *
get_set_ptr(set_nr)
  int set_nr;
{
  struct cat_set *ptr;
  
  ptr = sets;
  
  while (ptr != 0){
    if (ptr->set_nr == set_nr)
      return ptr;
    ptr = ptr->set_next;
  }
  return 0;
}
