
/* 
 * $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_get.c 1.2 90/05/20 $@(#)cat_get.c	1.2 89/12/01"

#include <stdio.h>
#include <nl_types.h>
#include <nl_type2.h>
#define min(a,b)  (a>b?b:a)

char *
cat_get_msg(catd, set_num, msg_num, buf, buflen)
  nl_catd catd;
  int set_num, msg_num, buflen;
  char *buf;
{
  register int i;
  struct cat_set_hdr *sets;
  struct cat_msg_hdr *msgs;
  struct cat_lib_set *setl;
  char *data;
  int first_msg;
  char *msg;
  char **msgs_addr;
  int msg_len;
  char *retcode;
  unsigned int start,offset;
  
  if ( ((int)catd == -1) || (catd->catd_set == 0) )
    return 0;

  sets = (struct cat_set_hdr *)catd->catd_set;
  msgs = (struct cat_msg_hdr *)catd->catd_msgs;
  data = catd->catd_data;

  retcode = (char *) 0;
  msg = "";

  if (catd->catd_type == MALLOC) {
    /*
     * Locate set
     */
    for (i = min(set_num, catd->catd_set_nr) - 1 ; i >= 0 ; i--){
      if (set_num == sets[i].shdr_set_nr){
        first_msg = sets[i].shdr_msg;
  
        /*
         * Locate message in set
         */
        for (i = min(msg_num, sets[i].shdr_msg_nr) - 1 ; i >= 0 ; i--){
          if (msg_num == msgs[first_msg + i].msg_nr){
            i += first_msg;
            msg = data + msgs[i].msg_ptr;
            msg_len = msgs[i].msg_len;

            if (buf != 0 && buflen != 0){
              /*
               * Requires a copy
               */
              int len = buflen > msg_len ? msg_len : buflen - 1;
              memcpy(buf, msg, len);
              buf[len] = '\0';
              msg = buf;
            }
            return msg;
          }
          if (msg_num > msgs[first_msg + i].msg_nr)
            return retcode;
        }
        return retcode;
      }
      if (set_num > sets[i].shdr_set_nr)
        return retcode;
    }
  } else
  if (catd->catd_type == SHARED_LIBRARY) {
    /*
     * get it from
     * a shared library
     */
    if (set_num > catd->catd_set_nr)
      return retcode;
    setl = &(((struct cat_lib_set*)(catd->catd_set))[set_num -1]);
    if (msg_num > setl->largest_number)
      return retcode;
    msgs_addr = (char**)catd->catd_msgs;
    if (msgs_addr[setl->first_in_set + msg_num -1]) {
      offset = (unsigned int)msgs_addr[setl->first_in_set +msg_num-1];
      start = (unsigned int)msgs_addr;
      msg = (char *)(start + offset);
      msg_len = strlen(msg);
      if (buf != 0 && buflen != 0){
        /*
         * Requires a copy
         */
        int len = buflen > msg_len ? msg_len : buflen - 1;
        memcpy(buf, msg, len);
        buf[len] = '\0';
        msg = buf;
      }
      if (msg[0])
        return msg;
    }
  }
  return retcode;
}
