Blame lib/Xm/xmlist.c

Packit b099d7
/*
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
 * 
Packit b099d7
 */
Packit b099d7
Packit b099d7
#include "xmlist.h"
Packit b099d7
Packit b099d7
/************************************************************
Packit b099d7
 *
Packit b099d7
 *  Stack code.
Packit b099d7
 *
Packit b099d7
 ************************************************************/
Packit b099d7
Packit b099d7
#define STACK_INC 25
Packit b099d7
Packit b099d7
/************************************************************
Packit b099d7
 *
Packit b099d7
 *  Stack Manipulation code.
Packit b099d7
 *
Packit b099d7
 ************************************************************/
Packit b099d7
Packit b099d7
/*	Function Name: _XmStackInit
Packit b099d7
 *	Description: Initializes the stack.
Packit b099d7
 *	Arguments: none
Packit b099d7
 *	Returns: the stack
Packit b099d7
 */
Packit b099d7
Packit b099d7
XmStack
Packit b099d7
_XmStackInit()
Packit b099d7
{
Packit b099d7
    return((XmStack) XtCalloc(sizeof(XmStackRec), (Cardinal) 1));
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmStackFree
Packit b099d7
 *	Description: Frees all data associated with the stack.
Packit b099d7
 *	Arguments: stack - the stack
Packit b099d7
 *	Returns: none
Packit b099d7
 */
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmStackFree(XmStack stack)
Packit b099d7
{
Packit b099d7
    XtFree((XtPointer) stack->elems);
Packit b099d7
    XtFree((XtPointer) stack);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmStackPush
Packit b099d7
 *	Description: Pushes an element onto the stack
Packit b099d7
 *	Arguments: stack - the stack
Packit b099d7
 *                 elem - element to push onto it.
Packit b099d7
 *	Returns: none
Packit b099d7
 */
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmStackPush(XmStack stack, XtPointer elem)
Packit b099d7
{
Packit b099d7
    if ((++stack->top) >= stack->alloc) {
Packit b099d7
	stack->alloc += STACK_INC;
Packit b099d7
	stack->elems = 
Packit b099d7
	    (XtPointer *) XtRealloc((XtPointer) stack->elems,
Packit b099d7
				    sizeof(XtPointer) * stack->alloc);
Packit b099d7
    }
Packit b099d7
Packit b099d7
    stack->elems[stack->top] = elem;
Packit b099d7
Packit b099d7
#ifdef STACK_DEBUG
Packit b099d7
    printf("Pushing %d as elem %d\n", (int) elem, stack->top);    
Packit b099d7
#endif
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmStackPop
Packit b099d7
 *	Description: Pops an element off of the stack.
Packit b099d7
 *	Arguments: stack - stack to pop off of.
Packit b099d7
 *	Returns: elem - the element that has been popped.
Packit b099d7
 */
Packit b099d7
Packit b099d7
XtPointer
Packit b099d7
_XmStackPop(XmStack stack)
Packit b099d7
{
Packit b099d7
    if (stack->top <= 0)
Packit b099d7
	return(NULL);		/* no elements on the stack. */
Packit b099d7
Packit b099d7
#ifdef STACK_DEBUG
Packit b099d7
    printf("Popping %d from elem %d\n", 
Packit b099d7
	   (int) stack->elems[stack->top], stack->top);
Packit b099d7
#endif
Packit b099d7
Packit b099d7
    return(stack->elems[(stack->top)--]);
Packit b099d7
}
Packit b099d7
Packit b099d7
/************************************************************
Packit b099d7
 *
Packit b099d7
 *  Queue code.
Packit b099d7
 *
Packit b099d7
 ************************************************************/
Packit b099d7
Packit b099d7
#ifdef QUEUE_DEBUG
Packit b099d7
#define QUEUE_INC 5
Packit b099d7
#else
Packit b099d7
#define QUEUE_INC 25
Packit b099d7
#endif
Packit b099d7
Packit b099d7
/************************************************************
Packit b099d7
 *
Packit b099d7
 *  Queue Manipulation code.
Packit b099d7
 *
Packit b099d7
 ************************************************************/
Packit b099d7
Packit b099d7
/*	Function Name: _XmQueueInit
Packit b099d7
 *	Description: Initializes the queue.
Packit b099d7
 *	Arguments: none
Packit b099d7
 *	Returns: the queue
Packit b099d7
 */
Packit b099d7
Packit b099d7
XmQueue
Packit b099d7
_XmQueueInit()
Packit b099d7
{
Packit b099d7
    return((XmQueue) XtCalloc(sizeof(XmQueueRec), (Cardinal) 1));
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmQueueFree
Packit b099d7
 *	Description: Frees all data associated with the queue.
Packit b099d7
 *	Arguments: queue - the queue
Packit b099d7
 *	Returns: none
Packit b099d7
 */
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmQueueFree(XmQueue queue)
Packit b099d7
{
Packit b099d7
    int count;
Packit b099d7
    _XmQElem *elem = queue->first;
Packit b099d7
    XmStack stack = _XmStackInit();
Packit b099d7
Packit b099d7
    for (count = 0; count < 2; count++) {
Packit b099d7
	while (elem != NULL) {
Packit b099d7
	    if (elem->alloced) 
Packit b099d7
		_XmStackPush(stack, (XtPointer) elem);
Packit b099d7
	    elem = elem->next;
Packit b099d7
	}
Packit b099d7
	
Packit b099d7
	elem = queue->free_elems;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    while ((elem = (_XmQElem *) _XmStackPop(stack)) != NULL)
Packit b099d7
	XtFree((XtPointer) elem);
Packit b099d7
Packit b099d7
    _XmStackFree(stack);
Packit b099d7
Packit b099d7
    XtFree((XtPointer) queue);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: QueuePush
Packit b099d7
 *	Description: Pushes an element onto the queue
Packit b099d7
 *	Arguments: queue - the queue
Packit b099d7
 *                 data_in - the data to push onto the queue.
Packit b099d7
 *	Returns: none
Packit b099d7
 */
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * This is being removed because its name was not changed when compiled
Packit b099d7
 * -DBX.  This means that there is already a QueuePush() defined in the
Packit b099d7
 * BX 3.1 bx.o, so integrating the EPak into BX causes multiply defined
Packit b099d7
 * symbols.  Luckily, this function is not currently used in EPak.  We
Packit b099d7
 * can remove this only when we don't support EPak integration into
Packit b099d7
 * BX 3.0 or BX 3.1.
Packit b099d7
 */
Packit b099d7
Packit b099d7
#ifdef notdef
Packit b099d7
void
Packit b099d7
QueuePush(XmQueue queue, XtPointer data_in)
Packit b099d7
{
Packit b099d7
    _XmQElem *elem = _Xm_GetNewElement(queue);
Packit b099d7
Packit b099d7
    _Xm_AddQueue(queue, queue->last, elem);
Packit b099d7
Packit b099d7
    if (queue->first == NULL) 
Packit b099d7
	queue->first = elem;
Packit b099d7
Packit b099d7
    queue->last = elem;
Packit b099d7
Packit b099d7
    elem->data = data_in;
Packit b099d7
Packit b099d7
#ifdef QUEUE_DEBUG
Packit b099d7
    printf("Pushing %d\n", (int) data_in);
Packit b099d7
#endif
Packit b099d7
}
Packit b099d7
#endif
Packit b099d7
Packit b099d7
/*	Function Name: _XmQueuePop
Packit b099d7
 *	Description: Pops an element off of the queue.
Packit b099d7
 *	Arguments: queue - queue to pop off of.
Packit b099d7
 *	Returns: elem - the element that has been popped.
Packit b099d7
 */
Packit b099d7
Packit b099d7
XtPointer
Packit b099d7
_XmQueuePop(XmQueue queue)
Packit b099d7
{
Packit b099d7
    _XmQElem *first = _Xm_RemQueue(&queue->first);
Packit b099d7
Packit b099d7
    if (queue->first == NULL)
Packit b099d7
	queue->last = NULL;
Packit b099d7
Packit b099d7
    if (first == NULL)
Packit b099d7
	return(NULL);
Packit b099d7
Packit b099d7
    _Xm_AddQueue(NULL, queue->free_elems, first);
Packit b099d7
Packit b099d7
#ifdef QUEUE_DEBUG
Packit b099d7
    printf("Popping %d\n", (int) first->data);
Packit b099d7
#endif
Packit b099d7
Packit b099d7
    return(first->data);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmQueueCount
Packit b099d7
 *	Description: Returns the number of items in the queue
Packit b099d7
 *	Arguments: queue - queue to check.
Packit b099d7
 *	Returns: number of items in queue.
Packit b099d7
 */
Packit b099d7
Packit b099d7
Packit b099d7
int
Packit b099d7
_XmQueueCount(XmQueue queue)
Packit b099d7
{
Packit b099d7
    register int i;
Packit b099d7
    register _XmQElem *elem = queue->first;
Packit b099d7
Packit b099d7
    for (i = 0; elem != NULL; i++)
Packit b099d7
	elem = elem->next;
Packit b099d7
Packit b099d7
    return(i);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmQueuePrint
Packit b099d7
 *	Description: Prints out the real and free nodes of the queue.
Packit b099d7
 *	Arguments: queue - queue to print.
Packit b099d7
 *	Returns: none.
Packit b099d7
 */
Packit b099d7
Packit b099d7
Packit b099d7
#ifdef QUEUE_DEBUG
Packit b099d7
void
Packit b099d7
_XmQueuePrint(XmQueue queue)
Packit b099d7
{
Packit b099d7
    _XmQElem *elem;
Packit b099d7
Packit b099d7
    printf("Elements:\n");
Packit b099d7
    for (elem = queue->first; elem != NULL; elem = elem->next)
Packit b099d7
	printf("Element - %d\n", elem->data);
Packit b099d7
Packit b099d7
    printf("Reverse Elements:\n");
Packit b099d7
    for (elem = queue->last; elem != NULL; elem = elem->prev)
Packit b099d7
	printf("Element - %d\n", elem->data);
Packit b099d7
Packit b099d7
    printf("Free Elements:\n");
Packit b099d7
    for (elem = queue->free_elems; elem != NULL; elem = elem->next)
Packit b099d7
	printf("Free Element - %d\n", elem->data);
Packit b099d7
}
Packit b099d7
#endif
Packit b099d7
Packit b099d7
/************************************************************
Packit b099d7
 *
Packit b099d7
 *  Internal Used (Utils Lib) functions.
Packit b099d7
 *
Packit b099d7
 ************************************************************/
Packit b099d7
Packit b099d7
/*	Function Name: _Xm_AddQueue
Packit b099d7
 *	Description: Adds an element to the queue, after the element specified.
Packit b099d7
 *	Arguments: queue - Queue to add to, if NULL then we may be adding
Packit b099d7
 *                         to the free items list.
Packit b099d7
 *                 after - the element is added after this one.
Packit b099d7
 *                 elem - element to add.
Packit b099d7
 *	Returns: none.
Packit b099d7
 */
Packit b099d7
Packit b099d7
void
Packit b099d7
_Xm_AddQueue(XmQueue queue, _XmQElem *after, _XmQElem *elem)
Packit b099d7
{
Packit b099d7
    if (elem != NULL) {
Packit b099d7
	elem->prev = after;
Packit b099d7
	if (after == NULL) 
Packit b099d7
	    /*
Packit b099d7
	     * If queue is NULL then this is being added to the 
Packit b099d7
	     * free elements queue, and we make certain assumptions, like
Packit b099d7
	     * we are always adding to then end of the list, so that
Packit b099d7
	     * we never will try to add before the first element.
Packit b099d7
	     */
Packit b099d7
	    if (queue != NULL) {
Packit b099d7
		elem->next = queue->first;
Packit b099d7
		if (elem->next != NULL)
Packit b099d7
		    elem->next->prev = elem;
Packit b099d7
	    }
Packit b099d7
	    else
Packit b099d7
		elem->next = NULL;
Packit b099d7
	else
Packit b099d7
	    elem->next = after->next;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    if (after != NULL) {
Packit b099d7
	if (after->next != NULL)
Packit b099d7
	    after->next->prev = elem;
Packit b099d7
	after->next = elem;
Packit b099d7
    }
Packit b099d7
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _Xm_RemQueue
Packit b099d7
 *	Description: Removes the specified element form a queue, and sets
Packit b099d7
 *                   the queue to point to the next element.
Packit b099d7
 *	Arguments: queue - the queue to remove it from.
Packit b099d7
 *	Returns: the element removed.
Packit b099d7
 */
Packit b099d7
Packit b099d7
_XmQElem *
Packit b099d7
_Xm_RemQueue(_XmQElem ** queue)
Packit b099d7
{
Packit b099d7
    _XmQElem * elem = *queue;
Packit b099d7
Packit b099d7
    if (elem != NULL) {
Packit b099d7
	*queue = elem->next;
Packit b099d7
Packit b099d7
	if (elem->next != NULL)
Packit b099d7
	    elem->next->prev = elem->prev;
Packit b099d7
Packit b099d7
	if (elem->prev != NULL)
Packit b099d7
	    elem->prev->next = elem->next;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    return(elem);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: GetNewElement
Packit b099d7
 *	Description: Gets an element off the free_elems list, allocates
Packit b099d7
 *                   more elems if necessary.
Packit b099d7
 *	Arguments: queue - the queue to get the element from.
Packit b099d7
 *	Returns: an element.
Packit b099d7
 */
Packit b099d7
Packit b099d7
_XmQElem *
Packit b099d7
_Xm_GetNewElement(XmQueue queue)
Packit b099d7
{
Packit b099d7
    _XmQElem *elem;
Packit b099d7
Packit b099d7
    if ((elem = _Xm_RemQueue(&queue->free_elems)) == NULL) {
Packit b099d7
	register int i;
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * We are out of free elements, alloc some more.
Packit b099d7
	 */
Packit b099d7
Packit b099d7
	queue->free_elems = (_XmQElem *) XtCalloc(sizeof(_XmQElem), QUEUE_INC);
Packit b099d7
	queue->free_elems->alloced = True;
Packit b099d7
Packit b099d7
	queue->free_elems->next = elem = queue->free_elems + 1;
Packit b099d7
	for (i = 1; i < (QUEUE_INC - 1); i++, elem++) {
Packit b099d7
	    elem->prev = elem - 1;
Packit b099d7
	    elem->next = elem + 1;
Packit b099d7
	}
Packit b099d7
	elem->prev = elem - 1;
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * Pop an element off the free elements queue.
Packit b099d7
	 */
Packit b099d7
Packit b099d7
	elem = _Xm_RemQueue(&queue->free_elems);
Packit b099d7
    }
Packit b099d7
Packit b099d7
    return(elem);
Packit b099d7
}
Packit b099d7
Packit b099d7
/************************************************************
Packit b099d7
 *
Packit b099d7
 *  List code.
Packit b099d7
 *
Packit b099d7
 ************************************************************/
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * This code is very dependant on the queue manipulation code, they
Packit b099d7
 * are sharing much functionality, several of these functions are just
Packit b099d7
 * wrappers around the queue maipulation code.
Packit b099d7
 */
Packit b099d7
Packit b099d7
/*	Function Name: _XmListInit
Packit b099d7
 *	Description: Initializes the list.
Packit b099d7
 *	Arguments: none
Packit b099d7
 *	Returns: the queue
Packit b099d7
 */
Packit b099d7
Packit b099d7
XmList
Packit b099d7
_XmListInit()
Packit b099d7
{
Packit b099d7
    return((XmList) _XmQueueInit());
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmListFree
Packit b099d7
 *	Description: Frees all data associated with the list.
Packit b099d7
 *	Arguments: list - the list
Packit b099d7
 *	Returns: none
Packit b099d7
 */
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmListFree(XmList list)
Packit b099d7
{
Packit b099d7
    _XmQueueFree((XmQueue) list);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmListAddAfter
Packit b099d7
 *	Description: Adds an element after the specified element.
Packit b099d7
 *	Arguments: list - the list
Packit b099d7
 *                 elem - The element to add this one after.
Packit b099d7
 *                        If NULL then add this element to the beginning of 
Packit b099d7
 *                        the list
Packit b099d7
 *                 data_in - the data to push onto the queue.
Packit b099d7
 *	Returns: The new added element.
Packit b099d7
 */
Packit b099d7
Packit b099d7
XmListElem *
Packit b099d7
_XmListAddAfter(XmList list, XmListElem *elem_in, XtPointer data_in)
Packit b099d7
{
Packit b099d7
    XmListElem *elem = (XmListElem *) _Xm_GetNewElement((XmQueue) list);
Packit b099d7
Packit b099d7
    _Xm_AddQueue((XmQueue) list, elem_in, elem);
Packit b099d7
Packit b099d7
    if (elem_in == NULL) 
Packit b099d7
	list->first = elem;
Packit b099d7
Packit b099d7
    if (elem_in == list->last)
Packit b099d7
	list->last = elem;
Packit b099d7
Packit b099d7
    elem->data = data_in;
Packit b099d7
Packit b099d7
    return(elem);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmListAddBefore
Packit b099d7
 *	Description: Adds an element before the specified element.
Packit b099d7
 *	Arguments: list - the list
Packit b099d7
 *                 elem - The element to add this one before.
Packit b099d7
 *                        If NULL then add this element to the end of 
Packit b099d7
 *                        the list.
Packit b099d7
 *                 data_in - the data to push onto the queue.
Packit b099d7
 *	Returns: The new added element.
Packit b099d7
 */
Packit b099d7
Packit b099d7
XmListElem *
Packit b099d7
_XmListAddBefore(XmList list, XmListElem *elem_in, XtPointer data_in)
Packit b099d7
{
Packit b099d7
    XmListElem *after;
Packit b099d7
Packit b099d7
    if (elem_in == NULL) 
Packit b099d7
	after = list->last;
Packit b099d7
    else
Packit b099d7
	after = elem_in->prev;
Packit b099d7
Packit b099d7
    return(_XmListAddAfter(list, after, data_in));
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmListRemove
Packit b099d7
 *	Description: Removes an element from the list.
Packit b099d7
 *	Arguments: list - the list to remove the element from.
Packit b099d7
 *	Returns: none.
Packit b099d7
 */
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmListRemove(XmList list, XmListElem *elem)
Packit b099d7
{
Packit b099d7
    XmListElem *dead = (XmListElem *) _Xm_RemQueue((_XmQElem **) &elem);    
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * if NULL is passed, then no action is taken.
Packit b099d7
     */
Packit b099d7
Packit b099d7
    if (dead == NULL) 
Packit b099d7
	return;
Packit b099d7
Packit b099d7
    if (list->first == dead)
Packit b099d7
	if ((list->first = dead->next) == NULL)
Packit b099d7
	    list->last = NULL;
Packit b099d7
Packit b099d7
    if (list->last == dead)
Packit b099d7
	if ((list->last = dead->prev) == NULL)
Packit b099d7
	    list->first = NULL;
Packit b099d7
Packit b099d7
    _Xm_AddQueue(NULL, list->free_elems, (_XmQElem *) dead);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmListCount
Packit b099d7
 *	Description: Returns the number of items in the list.
Packit b099d7
 *	Arguments: list - list to check.
Packit b099d7
 *	Returns: number of items in list.
Packit b099d7
 */
Packit b099d7
Packit b099d7
Packit b099d7
int
Packit b099d7
_XmListCount(XmList list)
Packit b099d7
{
Packit b099d7
    return(_XmQueueCount((XmQueue) list));
Packit b099d7
}
Packit b099d7
Packit b099d7
/*	Function Name: _XmListExec
Packit b099d7
 *	Description: Executes a function on all nodes in the list.
Packit b099d7
 *	Arguments: list - the list to use.
Packit b099d7
 *                 start - the element to start with.
Packit b099d7
 *                 end - the element to end with.
Packit b099d7
 *                 exec_func - the function to execute.
Packit b099d7
 *                 data - data to pass to the function.
Packit b099d7
 *	Returns: NULL is returned if all items from start to end 
Packit b099d7
 *               have been operated on.  Otherwise the node in which
Packit b099d7
 *               the operation stopped is returned.
Packit b099d7
 *
Packit b099d7
 * NOTES: If start is NULL the start is the first element in the list.
Packit b099d7
 *        If end is NULL then all elements after start will be searched.
Packit b099d7
 *        The list is always executed if forward order from start -> 
Packit b099d7
 *        	start->next, start->next->next...
Packit b099d7
 *        
Packit b099d7
 */
Packit b099d7
Packit b099d7
XmListElem *
Packit b099d7
_XmListExec(XmList list, XmListElem *start, XmListElem *end, 
Packit b099d7
	 XmListFunc func, XtPointer data)
Packit b099d7
{
Packit b099d7
    if (start == NULL)
Packit b099d7
	start = list->first;
Packit b099d7
Packit b099d7
    for ( ; (start != end) && (start != NULL); start = start->next) {
Packit b099d7
	if (!(*func)(start, data))
Packit b099d7
	    return(start);
Packit b099d7
    }
Packit b099d7
    
Packit b099d7
    return(NULL);
Packit b099d7
}
Packit b099d7
 
Packit b099d7
/*	Function Name: _XmListPrint
Packit b099d7
 *	Description: Prints out the real and free nodes of the list.
Packit b099d7
 *	Arguments: list - list to print.
Packit b099d7
 *	Returns: none.
Packit b099d7
 */
Packit b099d7
Packit b099d7
Packit b099d7
#ifdef QUEUE_DEBUG
Packit b099d7
void
Packit b099d7
_XmListPrint(XmList list)
Packit b099d7
{
Packit b099d7
    _XmQueuePrint((XmQueue) list);
Packit b099d7
}
Packit b099d7
#endif
Packit b099d7