#ifdef RCSID
static char *RCSid = 
   "$Header: oamh.h,v 2.6 96/10/15 12:37:51 ewinner: Stab $ ";
#endif /* RCSID */

/*----------------------------------------------------------------------------\
|  Copyright (c) Oracle Corporation 1989, 1994.  All Rights Reserved.         |
\----------------------------------------------------------------------------*/

/*
NAME
  oamh.h - Message Handling (LMS) routines for Office Automation products
DESCRIPTION

   The OA Message Handler module is designed to allow all OA products to use
the same lms functions for all nls calls.  This avoids the hassle of each
product writing and maintaining its own lms interface.

   Each product can have multiple files, but the msg code ranges should be
distinct.

Type OAMH_FNERR is for errors.  There should be no overlap in msg code
ranges between all products that use the facility.

This way we can look up a message based on product and msg code, or if we
know it is an error we can look it up by msg code alone.

Here is an example:

         prod_id   type_id     range
OAERR        0        0       10000 - 10999
OA           0        1           0 -  9999
MAILERR      1        0       11000 - 11999
MAIL         1        1           0 -  9999
CALERR       2        0       12000 - 13000
CAL          2        1           0 -  9999


NOTES
  The product and facility passed in using the oamha struct should be pointers
  to read-only constants that are not relocated (e.g. just pass in "OAE" or
  the like).  This is a requirement of lmsini/lmsrip.
MODIFIED
    ewinner    10/07/96 -  core3 upgrade 
    ewinner    10/11/94 -  duh, make the file compilable 
    ewinner    10/11/94 -  more shared oracle 
    ewinner    10/11/94 -  add text var to oamh for shared oracle support 
    strabosh   08/29/94 -  make product and facility point to constants
    strabosh    3/11/94 -  use fixed number of open files
    strabosh   12/13/93 -  change structure elements to CONST 
    strabosh   12/30/92 -  add oamhgmm 
    strabosh   07/16/92 -  add ref count to message handle instance 
    strabosh   07/09/92 -  fix prototype and add more documentation 
    strabosh   04/20/92 -  change oamhaftb to dvoid * 
  strabosh   04/15/92 -  include soa.h
  Trabosh    6/04/91 - added ref count to oamh
  Trabosh    5/16/91 - added oamhluc, oamhgbf, made oamhlum a macro
  Trabosh    4/16/91 - created, some parts taken from krishna and jackie's oam
*/

#ifndef OAMH
#define OAMH
#define OAMH_ORACLE

#ifndef SOA
#include <soa.h>
#endif

#ifndef OA
#include <oa.h>
#endif

#ifndef OAXM
#include <oaxm.h>
#endif

#ifndef LMS
#include <lms.h>
#endif

/*
** Special return status codes
*/
#define OAMHE_NONE   LMS_NOERR  /* No Error */
#define OAMHE_MERR   1000       /* Memory ERror - probably alloc failed */
#define OAMHE_LCX    1001       /* OAXM error - can't alloc/find context */
#define OAMHE_NLID   1002       /* No language ID - can't find it */
#define OAMHE_MCA    1003       /* Missing Create Attribute */
#define OAMHE_MHNF   1004       /* Message Handle Not Found */

/*
**  Macros
*/
#define OAMH_DCS     1024   /* Default Cache Size */
#define OAMH_FACLEN     8   /* Max size of facility - I just made this up    */
#define OAMH_PRDLEN    24   /* Max size of product name - I made this up too */

#define OAMH_PRANY   0    /* PRoduct ANY */

#define OAMH_FTANY   0    /* File Type ANY */
#define OAMH_FTERR   1    /* File Type ERRor */
#define OAMH_FTSTD   2    /* File Type STandarD */

/*
** OAMH Attribute flags
*/
#define oaMH_PRD    ((ub4)1<<0)         /* oamhaprd, oamhafac, oamhaftb */
#define oaMH_PID    ((ub4)1<<1)         /* oamhapid */
#define oaMH_TYP    ((ub4)1<<2)         /* oamhatyp */
#define oaMH_RNG    ((ub4)1<<3)         /* oamhabeg, oamhaend */
#define oaMH_CSH    ((ub4)1<<4)         /* oamhanms, oamhamnm */
#define oaMH_CRS    ((ub4)1<<5)         /* oamharcs */
#define oaMH_ENV    ((ub4)1<<6)         /* oamhaenv */

/*
** OA Message Handler Attributes
*/
typedef struct oamha
{
   ub4     oamhamask;

   CONST text   *oamhaprd; /* product name - what your product directory    */
                           /* will be under ORACLE_HOME (eg. "office")      */
   CONST text   *oamhafac; /* facility code - the prefix for your message    */
                        /* file and the string use to construct error msgs   */
                        /* (eg. "OFC" would use fle ofcus.msb and OFC-#####: */
   CONST dvoid  *oamhaftb; /* facility table */

   eword   oamhapid;    /* product id - ut product id (from utpr.h), */
                        /* register new products with toolkit group  */
   eword   oamhatyp;    /* type of message file: OAMH_FT* */
   eword   oamhabeg;    /* beginning of lms range */
   eword   oamhaend;    /* end of lms range */

   eword   oamhanms;    /* number of messages in locality */
   eword   oamhamnm;    /* estimated max number of messages */

   eword   oamharcs;    /* requested cache size */
   CONST text  *oamhaenv; /* environment var to translate to generated
			    directory name in which the message files
			    live */
} oamha;

/*
**  OA Message Handler Product specific info (PRIVATE)
*/
typedef struct oamhp
{
   eword   oamhppid;    /* product id */
   eword   oamhptyp;    /* type of message file (0 for errors) */
   eword   oamhpbeg;    /* beginning of lms range */
   eword   oamhpend;    /* end of lms range */
   eword   oamhpref;    /* reference count - number of times oamhadd called */

   lmshd  *oamhplms;    /* lms pointer to handle */

   CONST text *oamhpprd; /* product name */
   CONST text *oamhpfac; /* facility code */

   uword   oamhpacc;    /* number of times this handle was accessed - STAT */
   uword   oamhpopn;    /* number of times this handle was opened - STAT */
   CONST text *oamhpenv; /* env var for lookup of message files code */
   text  oamhpdir[128]; /* dir for lookup of message files code */
} oamhp;


/*
**  Description of handle caching scheme:
**     The number of open handles will be maintained between OAMH_MAXHDL and
**  OAMH_IDEAL.  After every OAMH_CACHE_CHECK access to lms we will close
**  any open handles that have not been accessed in OAMH_CACHE_CLOSE total
**  accesses, unless we are at the OAMH_IDEAL level.
**     The idea behind this is that we want to keep as few files open as
**  possible, but occasionally we will need to access several different
**  handles in a cycle which would prohibit having a low hard coded max on the
**  number of files.
*/
#define OAMH_MAXHDL        8   /* the maximum number of open handles */
#define OAMH_IDEAL         3   /* try to keep the number around here */

#define OAMH_CACHE_CLOSE  50  /* accesses after which handle may be closed */
#define OAMH_CACHE_CHECK  25  /* check cache for unused handles this often */

/*
**  OA Message Handle (contents PRIVATE)
*/
typedef struct oamh
{
   oaxmctx *oamhlcx;   /* pointer to global context manager */
   eword    oamhsiz;   /* number of product message handles allocated */
   eword    oamhnum;   /* number of product message handles used */
   oamhp   *oamharr;   /* array of product message handles */
   eword    oamhref;   /* reference count - number of times oamhini called */
   
   eword    oamheno;   /* holds errors encountered */

   lmshd    oamhhd[OAMH_MAXHDL];  /* array of lms handles */
   ub4      oamhahd[OAMH_MAXHDL]; /* last time this handle was accessed */
   eb1     *oamhcch[OAMH_MAXHDL]; /* message cache per handle */
   sword    oamhoph;   /* open handles */
   ub4      oamhopc;   /* fetch counter */

   sword    oamhmxh;   /* maximum opened handles - STAT */
   lxglo    *oamhglo; /* set in oamhad2() */
} oamh;

/*------------------------  PUBLIC FUNCTIONS  ------------------------------*/

/*
**  OAMHINI -  Message Handler INItialize
**    Create and initialize the oamh structure.  Takes the estimated number
**  of lms handles that will be requested.  This is only a guideline as
**  oamhadd will realloc the area if necessary.
*/
oamh *oamhini( /*_ oaxmctx *xmc, eword num _*/ );

/*
**  OAMHAD2 -  Message Handler ADD a product and set glo in context
**    Add a file to the message handler context.
**
**  mhctx    - the message handler context returned by oamhini (or from oaxm)
**  mha      - the message handler attribute structure which describes the
**             the file that should be added
*/
sword oamhad2( /*_ oamh *mhctx, oamha *mha, lxglo *glo _*/ );

/*
**  OAMHADD -  Message Handler ADD a product
**    Add a file to the message handler context.
**
**  mhctx    - the message handler context returned by oamhini (or from oaxm)
**  mha      - the message handler attribute structure which describes the
**             the file that should be added
*/
sword oamhadd( /*_ oamh *mhctx, oamha *mha _*/ );

/*
**  OAMHREM -  Message Handler REMove a product
**    Remove a product from message handler context.
*/
sword oamhrem( /*_ oamh *mhctx, eword prod_id, eword type_id _*/ );

/*
**  OAMHSHT -  Message Handler SHuTdown
**    Shut down message handler.  All files will be closed and memory freed.
*/
void  oamhsht( /*_ oamh *mhctx _*/ );

/*
**  OAMHLUC -  Message Handler Look Up and Copy message
**    Look up message based on product id and message file type and copy it
**  to the specified buffer.
**
**  mhctx    - the message handler context returned by oamhini (or from oaxm)
**  prodid   - the product code (or OAMH_PRANY to match any product)
**  mftype   - the message file type (or OAMH_FTANY to match any type)
**  msgcode  - the message id to retrieve
**  msgbuf   - buffer where the message should be copied
**  buflen   - size of the buffer
*/
text *oamhluc( /*_ oamh *mhctx, eword prodid, eword mftype, eword msgcode,
                   text *msgbuf, size_t buflen _*/ );

/*
**  OAMHLUM -  Message Handler Look Up Message
**    Look up message based on product id and message file type.
**
**  mhctx    - the message handler context returned by oamhini (or from oaxm)
**  prodid   - the product code (or OAMH_PRANY to match any product)
**  mftype   - the message file type (or OAMH_FTANY to match any type)
**  msgcode  - the message id to retrieve
*/
/* text *oamhlum (\*_ oamh *mhctx, eword prodid,
                      eword mftype, eword msgcode _*\); */
#define oamhlum(mhctx, prodid, mftype, msgcode) \
  oamhluc(mhctx, prodid, mftype, msgcode, NULLP(text), (size_t)0)

/*
**  OAMHGMS -  Message Handler Get MeSsage
**    Looks for a message in message files for a specific product.
*/
/* text *oamhgms (\*_ oamh *mhctx, eword prodid, eword msgcode _*\); */
#define oamhgms(mhctx, prodid, msgcode) \
  oamhlum(mhctx, prodid, (eword)OAMH_FTANY, msgcode)

/*
**  OAMHGBF -  Message Handler Get Message into BuFfer
**    Looks for a message in message files for a specific product and copies
**  it into the specified buffer.
*/
/* text *oamhgbf (\*_ oamh *mhctx, eword prodid, eword msgcode,
                      text *msgbuf, size_t buflen _*\); */
#define oamhgbf(mhctx, prodid, msgcode, msgbuf, buflen) \
  oamhluc(mhctx, prodid, (eword)OAMH_FTANY, msgcode, msgbuf, buflen)

/*
**  OAMHGMM -  Message Handler Get Multiple Messages
**    Fills a buffer with a consecutive string of messages.  Keeps on fetching
**  until the buffer is full or it can find another message.
**    This is a little inefficient since it has to repeat the handle lookup
**  in oamhluc each time, but it is expected that this won't be a time critical
**  function, so code sharing and maintainability are more important.
**
**  mhctx    - the message handler context returned by oamhini (or from lcx)
**  prodid   - the product code (or OAMH_PRANY to match any product)
**  msgcode  - the message id to retrieve
**  msgbuf   - buffer where the message should be copied
**  buflen   - size of the buffer
*/
text *oamhgmm( /*_ oamh *mhctx, eword prodid, eword msgcode,
                   text *msgbuf, size_t buflen _*/ );

/*
**  OAMHGEM -  Message Handler Get Error Message
**    Look up error message in all message files of type error.
*/
/* eword oamhgem (\*_ oamh *mhctx, eword msgcode _*\); */
#define oamhgem(mhctx, msgcode) \
  oamhlum(mhctx, (eword)OAMH_PRANY, (eword)OAMH_FTERR, msgcode)

/*
**  OAMHERR -  Message Handler get ERRor
*/
/* eword oamherr (\*_ oamh *mhctx _*\); */
#define oamherr(mhctx)  (mhctx->oamheno)

/*------------------------  PRIVATE FUNCTIONS  -----------------------------*/

/*
**  OAMHCCS -  Message Handler Compute Cache Size as a multiple of OAMH_DCS
*/
/* eword oamhccs (\*_ eword size _*\); */
#define oamhccs(size) \
  ((size) = OAMH_DCS*((size)/OAMH_DCS) + ((size)%OAMH_DCS ? OAMH_DCS : 0))

#endif  /* OAMH */

