/*
 * xcontext.c --
 *
 * Copyright (c) 1994 Software Research Associates, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Software Research Associates not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.  Software Research
 * Associates makes no representations about the suitability of this software
 * for any purpose.  It is provided "as is" without express or implied
 * warranty.
 */
 
#include "xlibInt.h" 

typedef struct CONTEXTCELLtag {
    int context;
    caddr_t data;
    struct CONTEXTCELLtag * lpNext;
} CONTEXTCELL;

typedef struct WINDOWCELLtag {
    HWND hwnd;
    CONTEXTCELL *head;
    struct WINDOWCELLtag *lpNext;
} WINDOWCELL;

static WINDOWCELL * contextHead = NULL;

int lastcontext = 0;

static CONTEXTCELL * 	GetWindowHead(HWND, int);
static void 		SetWindowHead(HWND, int, CONTEXTCELL *);

/*
 * XUniqueContext --
 *
 */

XContext
XrmUniqueQuark(void)
{
    return ++lastcontext;
}

/* 
 *	XSaveContext --
 *
 */

int
XSaveContext(Display *display, Window hwnd, XContext context, caddr_t data)
{
    CONTEXTCELL * lpCell, * lpHead;

    lpHead = (CONTEXTCELL *) GetWindowHead(hwnd, 1);
    for (lpCell = lpHead; lpCell != NULL; lpCell = lpCell->lpNext) {
	if (lpCell->context == context) {
	    lpCell->data = data;
	    break;
	}
    }

    if (lpCell == NULL) {
    	if ((lpCell = (CONTEXTCELL *) malloc(sizeof(CONTEXTCELL))) == NULL) {
    	    return XCNOMEM;
	}
	lpCell->context = context;
	lpCell->data = data;
	lpCell->lpNext = lpHead;
	SetWindowHead(hwnd, 1, lpCell);
    }

    return XCSUCCESS;
}

/*
 *	XFindContext --
 *
 */
int
XFindContext(Display *display, Window hwnd, XContext context, caddr_t *data)
{
    CONTEXTCELL * lpCell;
    
    for (lpCell = (CONTEXTCELL *) GetWindowHead(hwnd, 1); 
    	    lpCell != NULL; lpCell = lpCell->lpNext) {
	if (lpCell->context == context) {
	    *data = lpCell->data;
	    break;
	}
    }

    if (lpCell == NULL) {
    	return XCNOENT;
    }

    return XCSUCCESS;
}

/*
 *	XDeleteContext --
 *
 */
int
XDeleteContext(Display *display, Window hwnd, XContext context)
{
    CONTEXTCELL * lpCell, * lpPrev;

    
    for (lpPrev =  NULL, lpCell = (CONTEXTCELL *) GetWindowHead(hwnd, 1); 
    	    lpCell != NULL; lpPrev = lpCell, lpCell = lpCell->lpNext) {
	if (lpCell->context == context) {
	    break;
	}
    }

    if (lpCell == NULL) {
	return XCNOENT;
    }
 
    if (lpPrev == NULL) {
    	SetWindowHead(hwnd, 1, lpCell->lpNext);
    } else {
    	lpPrev->lpNext = lpCell->lpNext;
    }
    free(lpCell);
    return XCSUCCESS;
}


static 	CONTEXTCELL *
GetWindowHead(HWND hwnd, int display)
{
    WINDOWCELL * lpCell;

    for (lpCell = contextHead; lpCell != NULL; lpCell = lpCell->lpNext) {
	if (lpCell->hwnd == hwnd) {
	    break;
	}
    }

    if (lpCell == NULL) {
    	if ((lpCell = (WINDOWCELL *) malloc(sizeof(WINDOWCELL))) == NULL) {
    	    return NULL;
	}
	lpCell->hwnd = hwnd;
	lpCell->head = NULL;
	lpCell->lpNext = contextHead;
	contextHead = lpCell;
    }

    return lpCell->head;
}

static 	void
SetWindowHead(HWND hwnd,  int display, CONTEXTCELL * data)
{
    WINDOWCELL * lpCell;

    for (lpCell = contextHead; lpCell != NULL; lpCell = lpCell->lpNext) {
	if (lpCell->hwnd == hwnd) {
	    break;
	}
    }

    if (lpCell == NULL) {
	return;
    }
    lpCell->head = data;
}
