#undef DEBUG

#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>

#include <suntool/sunview.h>
#include <suntool/seln.h>

static Seln_client s_client;
static char *mifToken = "<MIFFile";
static isHoldShelf = 0;
char MifClipboardFileName[MAXPATHLEN + 1];
char mySeln[MAXPATHLEN + 1];

void SetSelnFileName(s)
char *s;
{
sprintf(mySeln, "%s%s", mifToken, s);
}

void FreeSeln()
{
seln_destroy(s_client);
}

char *GetSeln()
{
static char yourSeln[MAXPATHLEN + 1];
Seln_holder holder;
Seln_request *buffer;

/* I know what I have. */
if (isHoldShelf)
	return (mySeln);
holder = seln_inquire(SELN_SHELF);
if (seln_holder_same_process(&holder)) {
	isHoldShelf = 1;
	return (mySeln);
}

/* Ask the holder. */
buffer = seln_ask(&holder, SELN_REQ_CONTENTS_ASCII, 0, 0); 
strncpy(yourSeln, buffer->data + sizeof(Seln_attribute), sizeof(yourSeln));
return (yourSeln);
}

void AcquireSeln()
{
Export(0);
if (isHoldShelf) {
#ifdef DEBUG
	printf("redundant ACQUIRE\n");
#endif
	return;
}
else {
#ifdef DEBUG
	printf("ACQUIRE\n");
#endif
}
if (seln_acquire(s_client, SELN_SHELF) != SELN_SHELF) {
    isHoldShelf = 0;
	fprintf(stderr, "Could not acquire selection.");
}
else {
    isHoldShelf = 1;
/* 
If we wait, we REALLY acquire the selection. 
I don't know why.
Perhaps seln_acquire returns before asking the holder to yield? 
*/
	sleep(1);
}
}

static func_key_proc(client_data, args)
char *client_data;
Seln_function_buffer *args;
{
Seln_holder *holder;
Seln_response response;

switch (args->function) {
case SELN_FN_PUT:
#ifdef DEBUG
	if (isHoldShelf)
		printf("redundant PUT\n");
	else printf("PUT\n");
#endif
	break;
case SELN_FN_GET:
#ifdef DEBUG
	if (isHoldShelf)
		printf("GET self\n");
	else printf("GET other process\n");
#endif
	break;
}

response = seln_figure_response(args, &holder);
#ifdef DEBUG
printf("response = %d\n", response);
#endif
switch (response) {
case SELN_SHELVE:
#ifdef DEBUG
	if (isHoldShelf)
		printf("redundant SHELVE\n");
	else printf("SHELVE\n");
#endif
	AcquireSeln();
}
}

void ReportSelnEvent(eventp)
Event *eventp;
{
char *someSeln;

if (event_is_key_left(eventp)) {
/*
Propagates event to SS so that
it will call func_key_proc in the holder process. 
*/
	if (event_is_up(eventp))
		switch (event_id(eventp)) {
		case KEY_LEFT(8): /* GET */
			someSeln = GetSeln();
			if (strncmp(mifToken, someSeln, sizeof(mifToken)) != 0)
				break;
			if (strlen(someSeln) == 8)
				Edit(MifClipboardFileName, 1 /* intern */);
			else Edit(&(someSeln[8]), 0 /* don't intern */);
			break;
		case KEY_LEFT(6): /* PUT */
			AcquireSeln();
			break;
		}
}
#ifdef NOTDEF
Calling this messes everything up.
seln_report_event(s_client, eventp);
#endif
}

static Seln_result reply_proc(item, context, length)
Seln_attribute item;
Seln_replier_data *context;
int length;
{
int size, needed;
char *seln, *destp;

switch (context->rank) {
case SELN_SHELF:
    if (! isHoldShelf)
		return (SELN_DIDNT_HAVE);
	break;
default:
	return (SELN_DIDNT_HAVE);
}
switch (item) {
case SELN_REQ_CONTENTS_ASCII:
#ifdef DEBUG
	printf("REQ_CONTENTS_ASCII\n");
#endif
	if (context->context != NULL) {
		fprintf(stderr, "Could not send selection."); 
		return (SELN_DIDNT_HAVE);
	}
	context->context = mySeln;
	size = strlen(context->context);
	destp = (char *)context->response_pointer;
	needed = size + 4;
	if (size % 4 != 0)
		needed += 4 - size % 4;
	if (needed > length) {
		fprintf(stderr, "Not enough room for selection."); 
		return (SELN_DIDNT_HAVE);
	}
	strcpy(destp, context->context);
	destp += size;
	while ((int)destp % 4 != 0)
		*destp++ = '\0';
	context->response_pointer = (char **)destp;
	*context->response_pointer++ = 0;
	return (SELN_SUCCESS);
case SELN_REQ_YIELD:
#ifdef DEBUG
	printf("REQ_YIELD\n");
#endif
    isHoldShelf = 0;
    seln_done(reply_proc, SELN_SHELF);
	*context->response_pointer++ = (char *)SELN_SUCCESS;
	return (SELN_SUCCESS);
case SELN_REQ_BYTESIZE:
#ifdef DEBUG
	printf("REQ_BYTESIZE\n");
#endif
	*context->response_pointer++ = (char *)strlen(mySeln);
	return (SELN_SUCCESS);
case SELN_REQ_END_REQUEST:
#ifdef DEBUG
	printf("REQ_END_REQUEST\n");
#endif
	return (SELN_SUCCESS);
default:
	return (SELN_UNRECOGNIZED);
}
} 

void InitSeln()
{
#ifdef NOTDEF
seln_use_test_service();
#endif
sprintf(MifClipboardFileName, "%s/mifclipboard", getenv("HOME"));
s_client = seln_create(func_key_proc, reply_proc, reply_proc /* client data */);
if (s_client == NULL) {
	fprintf(stderr, "seln_create failed\n");
	exit(1);
}
}
