/*  
 * receive.c
 *
 * Copyright (c) 1992 Sun Microsystems, Inc.  All rights reserved.
 */

#include <xview/xview.h>
#include <xview/textsw.h>
#include <xview/panel.h>
#include <desktop/tt_c.h>
#include "chkrc.h"
#include "dbtt_ui.h"
#include "display_ui.h"

#define 	IS_SET(v,i)	(v&(1<<i))

/*
 * Global object definitions.
 */
extern	dbtt_frame_objects		*Dbtt_frame;
extern	display_display_popup_objects   *Display_display_popup;
extern  int				Display_value;

static	int	running = FALSE;

extern int trace_on;

/*
 * Global function definitions.
 */
extern int tprintf(Xv_opaque textsw, char *format, ...);

/* pat_receive() - this function is called whenever a message
 *		   arrives from ToolTalk. It pulls the message
 *		   using tt_message_receive(), pulls all the
 *		   optional arguments and/or contexts, and
 *		   dumps a formatted display of the message
 *		   to the screen.
 */
Notify_value
pat_receive(Notify_client client, int fd)
{
	Xv_opaque	txsw = Dbtt_frame->textsw;
	Tt_message	inmsg;
	int		mark;
	char		*label;
	char		*flag;
	char		*type;
	char		*string;
	int		n;
	int		i;
	int             int_value;
	char            *string_value;
	char            *slotname;
	unsigned char   *bytes_value;
	char		*hex_string;
	int		length;

	mark = tt_mark();

	inmsg = tt_message_receive();

	if (inmsg == NULL) return(NOTIFY_DONE);

	ttrc = tt_ptr_error(inmsg);
	if(ttrc != TT_OK)
	{
		tprintf(txsw, "Could not get message\n");
		tt_message_destroy(inmsg);
		tt_release(mark);
		return(NOTIFY_DONE);
	}

	if(running)
	{
		tprintf(txsw,
			"******************************************\n** MESSAGE **   id : %s\n", 
			(string = tt_message_id(inmsg)) ? string : "NULL!");

		label = "Tt_address";
		flag = IS_SET(Display_value, 0)?"--->":"    ";
		tprintf(txsw, "%s%14s : %s\n", flag, label,
			address_val(tt_message_address(inmsg)));
		if(string = tt_message_handler(inmsg))
		{
			label = "Handler";
			flag = IS_SET(Display_value, 1)?"--->":"    ";
			tprintf(txsw, "%s%14s : '%s'\n", flag, label, string);
		}

		if(string = tt_message_handler_ptype(inmsg))
		{	
			label = "Handler ptype";
			flag = IS_SET(Display_value, 2)?"--->":"    ";
			tprintf(txsw, "%s%14s : '%s'\n", flag, label, string);
		}

		if(string = tt_message_object(inmsg))
		{	
			label = "Object";
			flag = IS_SET(Display_value, 3)?"--->":"    ";
			tprintf(txsw, "%s%14s : '%s'\n", flag, label, string);
		}

		if(string = tt_message_otype(inmsg))
		{	
			label = "OTYPE";
			flag = IS_SET(Display_value, 4)?"--->":"    ";
			tprintf(txsw, "%s%14s : '%s'\n", flag, label, string);
		}

		if(string = tt_message_op(inmsg))
		{	
			label = "Op";
			flag = IS_SET(Display_value, 5)?"--->":"    ";
			tprintf(txsw, "%s%14s : '%s'\n", flag, label, string);
		}

		if((n = tt_message_opnum(inmsg)) != -1)
		{
			label = "Opnum";
			flag = IS_SET(Display_value, 6)?"--->":"    ";
			tprintf(txsw, "%s%14s : %d\n", flag, label, n);
		}

		label = "Tt_scope";
		flag = IS_SET(Display_value, 7)?"--->":"    ";
		tprintf(txsw, "%s%14s : %s\n", flag, label,
			scope_val(tt_message_scope(inmsg)));

		if(string = tt_message_session(inmsg))
		{
			label = "Session";
			flag = IS_SET(Display_value, 8)?"--->":"    ";
			tprintf(txsw, "%s%14s : '%s'\n", flag, label, string);
		}

		if(string = tt_message_file(inmsg))
		{
			label = "File name";
			flag = IS_SET(Display_value, 9)?"--->":"    ";
			tprintf(txsw, "%s%14s : '%s'\n", flag, label, string);
		}

		label = "Tt_category";
		flag = IS_SET(Display_value, 10)?"--->":"    ";
		tprintf(txsw, "%s%14s : %s\n", flag, label,
			category_val(
			tt_pattern_category(tt_message_pattern(inmsg))));

		label = "Tt_class";
		flag = IS_SET(Display_value, 11)?"--->":"    ";
		tprintf(txsw, "%s%14s : %s\n", flag, label,
			class_val(tt_message_class(inmsg)));

		label = "Tt_disposition";
		flag = IS_SET(Display_value, 12)?"--->":"    ";
		tprintf(txsw, "%s%14s : %s\n", flag, label,
			disposition_val(tt_message_disposition(inmsg)));

		label = "Tt_state";
		flag = IS_SET(Display_value, 13)?"--->":"    ";
		tprintf(txsw, "%s%14s : %s\n", flag, label,
			state_val(tt_message_state(inmsg)));

		label = "Status";
		flag = IS_SET(Display_value, 14)?"--->":"    ";
		tprintf(txsw, "%s%14s : %s\n", flag, label, 
			tt_errors(n = tt_message_status(inmsg)));

		if(string = tt_message_status_string(inmsg))
		{
			label = "Status string";
			flag = IS_SET(Display_value, 15)?"--->":"    ";
			tprintf(txsw, "%s%14s : '%s'\n", flag, label, string);
		}

		if(string = tt_message_sender(inmsg))
		{
			label = "Sender";
			flag = IS_SET(Display_value, 16)?"--->":"    ";
			tprintf(txsw, "%s%14s : '%s'\n", flag, label, string);
		}

		if(string = tt_message_sender_ptype(inmsg))
		{
			label = "Sender ptype";
			flag = IS_SET(Display_value, 17)?"--->":"    ";
			tprintf(txsw, "%s%14s : '%s'\n", flag, label, string);
		}

		label = "Uid";
		flag = IS_SET(Display_value, 18)?"--->":"    ";
		tprintf(txsw, "%s%14s : %d\n", flag, label,
			(int)tt_message_uid(inmsg));

		label = "Gid";
		flag = IS_SET(Display_value, 19)?"--->":"    ";
		tprintf(txsw, "%s%14s : %d\n", flag, label,
			(int)tt_message_gid(inmsg));


		/* Get the arguments associated with this message */

		label = "Argument Count";
		flag = IS_SET(Display_value, 20)?"--->":"    ";
		tprintf(txsw, "%s%14s : %d\n", flag, label,
			n = tt_message_args_count(inmsg));

		for(i = 0; i < n; i++)
		{
			label = "Argument";
			flag = "    ";
			tprintf(txsw, "%s%11s[%d] : %s/%s\t-",
				flag, label, i,
				mode_val(tt_message_arg_mode(inmsg, i)),
				((type = tt_message_arg_type(inmsg, i)) == NULL) ?
				"" : type );

			ttrc = tt_message_arg_bval(inmsg,
			                           i,
			                           &bytes_value,
			                           &length);
			if ((ttrc != TT_OK) && (ttrc != TT_ERR_POINTER)) {
				tprintf(txsw, "\n");
				perror_tt(ttrc,
			    	  	  "tt_message_arg_bval(inmsg, i, &bytes_value, &length)",
			      	   	  __FILE__, __LINE__);
				tt_message_destroy(inmsg);
				tt_release(mark);
				return(NOTIFY_DONE);
			}

			if (ttrc != TT_ERR_POINTER) {
				string_value = tt_message_arg_val(inmsg, i);
				ttrc = tt_ptr_error(string_value);
				if (ttrc != TT_OK) {
					tprintf(txsw, "\n");
					perror_tt(ttrc,
				    	  	  "tt_message_arg_val(inmsg, i)",
				      	   	  __FILE__, __LINE__);
					tt_message_destroy(inmsg);
					tt_release(mark);
					return(NOTIFY_DONE);
				}

				if (!string_value) { 
					tprintf(txsw, " (NULL)\n");   
				} else if (strlen(string_value) == length) {
					tprintf(txsw, " '%s'\n", string_value);
				}
				else {
					int j;


					hex_string = (char *)malloc(2 * int_value + 1);
					for (j=0; j < int_value; j++) {
						sprintf(hex_string+j*2,
							"%2X",
					        	bytes_value[j]);
					}

					tprintf(txsw, " %s\n", hex_string);
					free(hex_string);
				}
			}
			else {
			        ttrc = tt_message_arg_ival(inmsg, i, &int_value);
				if ((ttrc != TT_OK) && (ttrc != TT_ERR_NUM)) {
					chkrc (tt_message_arg_ival(inmsg, i, &int_value));
					tprintf(txsw, "\n");
					tt_message_destroy(inmsg);
					tt_release(mark);
					return(NOTIFY_DONE);
				}
				else if (ttrc == TT_ERR_NUM) {
					tprintf(txsw, " (No Value Set)\n");
				}
				else {
					tprintf(txsw, " %d\n", int_value);
				}
			}
		}

		/* Get contexts/"keyword paramaters" associated with
		 * this message.
		 */

                label = "Context Count";
                flag = IS_SET(Display_value, 23)?"--->":"    ";

		/* Get the count of how many name/value pairs there are... */
		n = tt_message_contexts_count(inmsg);
		ttrc = tt_int_error(n);
		if (tt_is_err(ttrc)) {
			fprintf(stderr,
				"\npat_recieve: tt_message_contexts_count(inmsg): %s\n",
				tt_status_message(ttrc));
			tprintf(txsw, "\n");
			tt_message_destroy(inmsg);
			tt_release(mark);
			return(NOTIFY_DONE);
		}

                tprintf(txsw, "%s%14s : %d\n", flag, label, n);

		if (trace_on) {
			printf("\n--------------- Receive Code -------------------------\n");
			printf("\tint    tt_message_contexts_count() == %d;\n\n", n);
		}


		/* For each name/value pair, print out the contents of the
		 * context.  Since there is no way of knowing whether the
		 * value of this context is an integer, binary string, or
		 * character string, we have to try each in turn, looking
		 * at Tt_status return values, to determine which format
		 * this is.
		 */
		for(i = 0; i < n; i++)
		{
			label = "Context Slot";
			flag = "    ";
			slotname = tt_message_context_slotname(inmsg, i);
			ttrc = tt_ptr_error(slotname);
			if (tt_is_err(ttrc)) {
				fprintf(stderr,
					"\npat_recieve: tt_message_context_slotname(inmsg, %d): %s\n",
					i, tt_status_message(ttrc));
				tprintf(txsw, "\n");
				break;
			}

			tprintf(txsw, "%s%11s[%d] : name = %s/", flag,
				label, i, slotname);

			/* Try it as an integer */
			ttrc = tt_message_context_ival(inmsg, slotname,
						      &int_value);

			if (ttrc == TT_OK)
			{
				/* It's an integer */

                                tprintf(txsw, "value (integer)  = %d\n",
					int_value);
			}
			else
			if (ttrc == TT_ERR_NUM)
			{
				/* It's a char string or binary string */

				/* Try it as a binary string... */
				ttrc = tt_message_context_bval(inmsg, slotname,
							&bytes_value, &length);

				/* always check for errors, just to be safe */
				if (ttrc != TT_OK) {
					tprintf(txsw, "\n");
					break;
				}

				if (!bytes_value) { 
					tprintf(txsw, " (NULL)\n");   
				} else if (strlen((char *)bytes_value) == length) {
					/* ..it's a char string */
					tprintf(txsw, "value (char) = '%s'\n",
						bytes_value);
				}
				else
				{
					/* ..it's a hex string */
					int j;


					hex_string = (char *)malloc(6 * length);
					for (j = 0; j < length; j++) {
						sprintf(hex_string + j * 6,
							"%2X",
							bytes_value[j]);
					}
 
					tprintf(txsw, "value (hex) = %s\n",
						hex_string);
					free(hex_string);
				}
			}
			else
			{
				/* Error of some type */
				tprintf(txsw, "\n");
				break;
			}
		}
	}
	tt_message_destroy(inmsg);
	tt_release(mark);
	return(NOTIFY_DONE);
}

start_mon()
{
	running = TRUE;
}

stop_mon()
{
	running = FALSE;
}
