/*!***************************************************************************

  module      : RTE_Message.cpp

  -------------------------------------------------------------------------

  responsible : JoergM

  special area: RTE
  description : Function to save Kernel Messagelist 

  last changed: 2001-01-11  17:38
  see also    : 

  -------------------------------------------------------------------------



    ========== licence begin  GPL
    Copyright (c) 2001-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end




*****************************************************************************/



/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/

#include "RunTime/RTE_Message.hpp"
#include "SAPDBCommon/SAPDB_ToString.hpp"
#include "heo60_2.h"

#ifdef NMP
extern "C" void *alloca(size_t);
#endif

/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/

#if COMPILEMODE_MSP00 >= SLOW_MSP00	
#define COMPLETE_INFO_LINE
#endif

// Message Text limit is used for several reasons.
// dbmgetf reads out knldiag on a line by line base and copies atmost
// 255 character per line. Each knldiag line begins with 44 characters of 
// header information. Two lines on an 80 character display 160 minus 44 character
// header result in 116 character. One character less to prevent automatic wrap
// around leads to 115.
// This value is only needed due to the line oriented output of knldiag.
#define MESSAGE_TEXT_LIMIT 115

/*===========================================================================*
 *  MACROS                                                                   *
 *===========================================================================*/



/*===========================================================================*
 *  LOCAL CLASSES, STRUCTURES, TYPES, UNIONS ...                             *
 *===========================================================================*/



/*===========================================================================*
 *  STATIC/INLINE FUNCTION PROTOTYPES                                        *
 *===========================================================================*/

static void ShowMessage(SAPDB_UInt1 const      msgMedia,
                        SAPDB_Int4             msgCount, 
                        tsp3_msg_type_Param    msgType, 
                        SAPDB_Int4             msgNo,
                        tsp00_C8            &  msgLabel, 
                        const SAPDBErr_MessageList & nextMsg);

/*===========================================================================*
 *  METHODS                                                                  *
 *===========================================================================*/

void RTE_Message(const SAPDBErr_MessageList &   msgList,
                 SAPDB_UInt1 const              msgMedia)
{
    if ( !msgList.IsEmpty() )
    {
        const SAPDBErr_MessageList * nextMsg = &msgList;
        const SAPDBErr_MessageList * lastMsg;
        SAPDB_Int4                        msgCount;
        tsp3_msg_type_Param               msgType;
        SAPDB_Int4                        msgNo;
        tsp00_C8                          msgLabel;

        for ( msgCount = 0;
              nextMsg != 0;
              msgCount++ )
        {
            lastMsg = nextMsg;
            nextMsg = nextMsg->NextMessage();
        }

        switch( lastMsg->Type() )
        {
        case SAPDBErr_MessageList::Error:   msgType = sp3m_error;
            break;
        case SAPDBErr_MessageList::Warning: msgType = sp3m_warning;
            break;
        case SAPDBErr_MessageList::Info:    msgType = sp3m_info;
            break;
        default:                            msgType = sp3m_nil;
            break;
        }

        msgNo = lastMsg->ID();

        msgLabel.c2p(lastMsg->Component());

        for ( nextMsg = &msgList; 
              msgCount > 0 ; 
              --msgCount, nextMsg = nextMsg->NextMessage() )
        {
            ShowMessage(msgMedia, msgCount, msgType, msgNo, msgLabel, *nextMsg);
        }
    }
}

/*===========================================================================*
 *  STATIC/INLINE FUNCTION CODE                                              *
 *===========================================================================*/

static void ShowLongline(const SAPDB_Char *line, 
                         SAPDB_Int4 len,
                         const SAPDB_Char *intro,
                         SAPDB_UInt1 const      msgMedia,
                         tsp3_msg_type_Param    msgType, 
                         SAPDB_Int4             msgNo,
                         tsp00_C8             & msgLabel)
{
    SAPDB_Int4 introLen = (SAPDB_Int4)strlen(intro);
    SAPDB_Int4 maxLen;
    SAPDB_Char msgText[MESSAGE_TEXT_LIMIT+1];
    const SAPDB_Char *tmpName = line;
    SAPDB_Int4  tmpLen = (len == 0 ? (SAPDB_Int4)strlen(line) : len);

    if ( introLen > 10 ) 
    {
        intro = "";
        introLen = 0;
    }

    maxLen = (sizeof(msgText) - 1) - introLen;

    while ( tmpLen > maxLen )
    {
        memset(msgText,' ',sizeof(msgText));
        if ( introLen > 0 )
        {
            memcpy(msgText, intro, introLen);
        }
        memcpy(&msgText[introLen], tmpName, maxLen);
        msgText[introLen+maxLen] = 0;

        eo60k_Message((tsp3_priority_Param)msgMedia, msgType, msgNo, msgLabel.asCharp(), msgText );
        tmpName  += maxLen;
        tmpLen   -= maxLen;
    }

    memset(msgText,' ',sizeof(msgText));
    if ( introLen > 0 )
    {
        memcpy(msgText, intro, introLen);
    }
    memcpy(&msgText[introLen], tmpName, tmpLen);
    msgText[introLen+tmpLen] = 0;
    eo60k_Message((tsp3_priority_Param)msgMedia, msgType, msgNo, msgLabel.asCharp(), msgText );
}

/*---------------------------------------------------------------------------*/

#ifdef COMPLETE_INFO_LINE

/*---------------------------------------------------------------------------
  Function: FindFilename
  Description: Return the filename without directories
  ---------------------------------------------------------------------------*/
static const SAPDB_Char *FindFilename(const SAPDB_Char *fileName)
{
    const SAPDB_Char *lastChar = fileName;
    const SAPDB_Char *lastEntry = fileName;

    while ( 0 != *lastChar )
    {
#if defined(_WIN32)
        if ( *lastChar == '\\' || *lastChar == '/' )
        {
            do
            {
                ++lastChar;
            } while ( *lastChar == '\\' || *lastChar == '/' );

            if ( *lastChar ) lastEntry = lastChar; 
        }
#else
        if ( *lastChar == '/' )
        {
            do
            {
                ++lastChar;
            } while ( *lastChar == '/' );

            if ( *lastChar ) lastEntry = lastChar; 
        }
#endif
        ++lastChar;
    }

    return lastEntry;
}

/*---------------------------------------------------------------------------
  Function: ShowFileLine
  Description: Show the message __FILE__ and __LINE__ parameter
  ---------------------------------------------------------------------------*/
static void ShowFileLine(SAPDB_UInt1 const      msgMedia,
                         tsp3_msg_type_Param    msgType, 
                         SAPDB_Int4             msgNo,
                         tsp00_C8             & msgLabel, 
                         const SAPDB_Char     * intro,
                         const SAPDBErr_MessageList & nextMsg)
{
    SAPDB_Char *tmpName;
    SAPDB_Int4 len;
    SAPDB_ToStringClass numberString(nextMsg.LineNumber());

    const SAPDB_Char *fileName = FindFilename(nextMsg.FileName());

    len = (SAPDB_Int4) (
          strlen(fileName) 
        + strlen(":") 
        + strlen((SAPDB_Char *)numberString) );
    tmpName = (SAPDB_Char *)alloca( len+1 );

    strcpy(tmpName, fileName);
    strcat(tmpName, ":");
    strcat(tmpName, (SAPDB_Char *)numberString);

    ShowLongline(tmpName, len, intro, msgMedia, msgType, msgNo, msgLabel);
}

#endif /* COMPLETE_INFO_LINE */

/*---------------------------------------------------------------------------
  Function: ShowMesgPara
  Description: Show the message parameter DateTime,Component,Type,ID separated by blank
  ---------------------------------------------------------------------------*/
static void ShowMesgPara(SAPDB_UInt1 const      msgMedia,
                         tsp3_msg_type_Param    msgType, 
                         SAPDB_Int4             msgNo,
                         tsp00_C8             & msgLabel, 
                         const SAPDB_Char     * intro,
                         const SAPDBErr_MessageList & nextMsg)
{
    SAPDB_Char *tmpName;
    SAPDB_Int4 len;
    SAPDB_ToStringClass idString(nextMsg.ID());
    len = (SAPDB_Int4)(strlen(nextMsg.DateTime(true)) + strlen(" ")
        + strlen(nextMsg.Component()) + strlen(" ")
        + strlen(nextMsg.Type(true)) + strlen(" ")
        + strlen((SAPDB_Char *)idString));
    tmpName = (SAPDB_Char *)alloca( len+1 );

    strcpy(tmpName, nextMsg.DateTime(true));
    strcat(tmpName, " ");
    strcat(tmpName, nextMsg.Component());
    strcat(tmpName, " ");
    strcat(tmpName, nextMsg.Type(true));
    strcat(tmpName, " ");
    strcat(tmpName, (SAPDB_Char *)idString);
    ShowLongline(tmpName, len, intro, msgMedia, msgType, msgNo, msgLabel);
}

/*---------------------------------------------------------------------------
  Function: ShowMesgText
  Description: Show the message text + optional system return code
  ---------------------------------------------------------------------------*/
static void ShowMesgText(SAPDB_UInt1 const      msgMedia,
                         tsp3_msg_type_Param    msgType, 
                         SAPDB_Int4             msgNo,
                         tsp00_C8             & msgLabel, 
                         const SAPDB_Char     * intro,
                         const SAPDBErr_MessageList & nextMsg)
{
    SAPDB_Char *tmpName;
    SAPDB_Int4 len;
    SAPDB_ToStringClass rcString(nextMsg.SystemRC());

    len = (SAPDB_Int4)strlen(nextMsg.Message());
    if ( nextMsg.SystemRC() != 0 )
    {
        len += (SAPDB_Int4)strlen("[");
        len += (SAPDB_Int4)strlen((SAPDB_Char *)rcString);
        len += (SAPDB_Int4)strlen("]");
    }
    tmpName = (SAPDB_Char *)alloca( len+1 );

    strcpy(tmpName, nextMsg.Message());
    if ( nextMsg.SystemRC() != 0 )
    {
        strcat(tmpName, "[");
        strcat(tmpName, (SAPDB_Char *)rcString);
        strcat(tmpName, "]");
    }

    ShowLongline(tmpName, len, intro, msgMedia, msgType, msgNo, msgLabel);
}

/*---------------------------------------------------------------------------*/

static void ShowMessage(SAPDB_UInt1 const      msgMedia,
                        SAPDB_Int4             msgCount, 
                        tsp3_msg_type_Param    msgType, 
                        SAPDB_Int4             msgNo,
                        tsp00_C8             & msgLabel, 
                        const SAPDBErr_MessageList & nextMsg)
{
    if ( msgCount == 1 )
    {
#ifdef COMPLETE_INFO_LINE
        ShowFileLine(msgMedia, msgType, msgNo, msgLabel, "", nextMsg);
        ShowMesgPara(msgMedia, msgType, msgNo, msgLabel, "", nextMsg);
#endif
        ShowMesgText(msgMedia, msgType, msgNo, msgLabel, "", nextMsg);
    }
    else
    {
#ifdef COMPLETE_INFO_LINE
        ShowFileLine(msgMedia, msgType, msgNo, msgLabel, "+ ", nextMsg);
#endif
        ShowMesgPara(msgMedia, msgType, msgNo, msgLabel, "+ ", nextMsg);
        ShowMesgText(msgMedia, msgType, msgNo, msgLabel, "-   ", nextMsg);
    }
}

/*===========================================================================*
 *  END OF CODE                                                              *
 *===========================================================================*/
