campo-sirio/cb5/r4area.c

625 lines
13 KiB
C
Raw Normal View History

/* r4area.c (c)Copyright Sequiter Software Inc., 1990-1994. All rights reserved. */
#include "d4all.h"
/************************************************************
** Function: area4create()
*
* PARAMETERS:
* GROUP4* group - pointer to the containing GROUP4
* long height - height of the area in 1000's of an inch
* short is_header - flag indicating whether area is header or footer
* char* expression - character string for suppression condition
*
* DESCRIPTION: allocates the memory for an AREA4 and does initial setup
* of internal members, then adds to appropriate list in containing group
*
* RETURNS: an AREA4 pointer on success, NULL on failure
*
* By: Raymond Cypher
*
* HISTORY:
*
*/
AREA4 * S4FUNCTION area4create( GROUP4 *group, long height, short is_header, char *expression )
{
AREA4 *area, *area_on;
EXPR4 *expr;
int i;
if( !group )
return NULL;
if( height < 0 )
{
e4describe( group->report->code_base, e4parm, E4_REP_AHEIGHT, 0, 0 );
return 0;
}
/* is suppression condition is provided, parse and check */
if( expression )
{
expr = expr4parse( group->report->relate->data, expression );
if( expr == 0 )
{
e4describe( group->report->code_base, e4area_create, E4_REP_AEXPR, 0, 0 );
return 0;
}
}
else
expr = NULL;
/* allocate AREA4 */
area = (AREA4 *) u4alloc_free( group->report->code_base, sizeof(AREA4) );
if(area == 0)
{
e4describe( group->report->code_base, e4area_create, E4_REP_AMEM, 0, 0 );
return 0;
}
/* set internal members */
area->height = height;
area->suppression_condition = expr;
area->group = group;
area->allow_pagebreaks = 1;
area->report = group->report;
area->is_header = is_header;
/* insert AREA4 into appropriate list in GROUP4 struct and then re-number
the areas */
if( is_header )
{
l4add( &group->header_areas, area );
}
else
{
l4add( &group->footer_areas, area );
}
i = 1;
if( is_header )
area_on = (AREA4 *) l4first( &group->header_areas );
else
area_on = (AREA4 *) l4first( &group->footer_areas );
while(area_on )
{
area_on->position = i;
if( is_header )
area_on = (AREA4 *) l4next( &group->header_areas, area_on );
else
area_on = (AREA4 *) l4next( &group->footer_areas, area_on );
i++;
}
return area;
}
/************************************************************
** Function: area4free()
*
* PARAMETERS: AREA4* area - pointer to area to be freed
*
* DESCRIPTION: frees the specified area, including any contained objects
*
* By: Raymond Cypher
*
* HISTORY:
*
*/
void S4FUNCTION area4free( AREA4 *area )
{
OBJ4 *obj_on;
/* free the supppression condition */
if( area->suppression_condition != NULL )
{
expr4free( area->suppression_condition );
}
/* free the contained objects */
while( (obj_on=(POBJ4)l4first(&area->objects)) != NULL )
{
obj4delete( obj_on );
}
/* Destroy the associated window */
#ifdef S4WINDOWS
if( area->hWnd )
{
DestroyWindow( area->hWnd );
area->hWnd = 0;
}
#endif
/* remove from the groups list */
if( area->is_header )
l4remove( &area->group->header_areas, area );
else
l4remove( &area->group->footer_areas, area );
/* free the memory */
u4free( area );
}
/************************************************************
** Function: area4insert_object()
*
* PARAMETERS: LIST4* list - list to insert the object into
* POBJ4 obj - object to be inserted
*
* DESCRIPTION: inserts the object into the list, if the
* object falls within the boundaries of another object it
* is inserted into the bounding objects list
*
* By: Raymond Cypher
*
* HISTORY:
*
*/
void area4insert_object( LIST4 *list, POBJ4 obj )
{
POBJ4 obj_on;
obj_on = (POBJ4)l4first( list );
while( obj_on )
{
/* if the object is inside another object */
if( obj->x > obj_on->x && obj->y > obj_on->y &&
obj->w+obj->x < obj_on->w+obj_on->x &&
obj->h+obj->y < obj_on->h+obj_on->y )
{
obj->container = obj_on;
area4insert_object( &obj_on->contained, obj );
return;
}
obj_on = (POBJ4)l4next( list, obj_on );
}
/* add at beginning or end of list */
if( !obj->background )
l4add( list, obj );
else
l4add_before( list, l4first(list), obj );
return;
}
/************************************************************
** Function: area4insert_y()
*
* PARAMETERS: LIST4* list - list to insert object into
* POBJ4 obj_out - object to be inserted
*
* DESCRIPTION: inserts the specified object into the list
* on the basis of the y coordinate
*
* By: Raymond Cypher
*
* HISTORY:
*
*/
void area4insert_y( LIST4 *list, POBJ4 obj_out )
{
POBJ4 obj_on;
int add_flag;
obj_on = (POBJ4)l4first( list );
if( !obj_on )
{
l4add( list, obj_out );
}
else
{
add_flag = 0;
while( obj_on )
{
if( obj_out->y < obj_on->y )
{
l4add_before( list, obj_on, obj_out );
add_flag = 1;
}
if( !add_flag )
obj_on = (POBJ4)l4next( list, obj_on );
else
obj_on = NULL;
}
if( !add_flag )
l4add( list, obj_out );
}
}
/************************************************************
** Function: area4insert_xrev()
*
* PARAMETERS: LIST4* list - list to insert object into
* POBJ4 obj_out - object to be inserted
*
* DESCRIPTION: inserts the specified object into the list
* on the basis of the x coordinate
*
* By: Raymond Cypher
*
* HISTORY:
*
*/
void area4insert_xrev( LIST4 *list, POBJ4 obj_out )
{
POBJ4 obj_on;
int add_flag;
obj_on = (POBJ4)l4first( list );
if( !obj_on )
{
l4add( list, obj_out );
}
else
{
add_flag = 0;
while( obj_on )
{
if( obj_out->x > obj_on->x )
{
l4add_before( list, obj_on, obj_out );
add_flag = 1;
}
if( !add_flag )
obj_on = (POBJ4)l4next( list, obj_on );
else
obj_on = NULL;
}
if( !add_flag )
l4add( list, obj_out );
}
}
/************************************************************
** Function: area4sort_list()
*
* PARAMETERS: LIST4 *list - list containing OBJ4 structures
*
* DESCRIPTION: sorts the list of objects
*
* By: Raymond Cypher
*
* HISTORY:
*
*/
void area4sort_list( LIST4 *list )
{
LIST4 hold_list, int_list;
POBJ4 obj_on, obj_out, obj_bound;
long ybound;
memset( &hold_list, 0, sizeof(LIST4) );
memset( &int_list, 0, sizeof(LIST4) );
while( (obj_out = (POBJ4)l4pop(list)) != NULL )
{
area4insert_y( &hold_list, obj_out );
}
while( hold_list.n_link > 0 )
{
obj_bound = (POBJ4)l4first( &hold_list );
l4remove( &hold_list, obj_bound );
area4insert_xrev( &int_list, obj_bound );
ybound = obj_bound->y;
obj_on = (POBJ4)l4first( &hold_list );
while( obj_on && obj_on->y == ybound )
{
l4remove( &hold_list, obj_on );
area4insert_xrev( &int_list, obj_on );
obj_on = (POBJ4)l4first( &hold_list );
}
while( (obj_out = (POBJ4)l4pop( &int_list)) != NULL )
l4add( list, obj_out );
}
}
/************************************************************
** Function: area4add_object()
*
* PARAMETERS: AREA4* area - area to which an object is to be added
* OBJ4* obj_add - object to be added to the area
*
* DESCRIPTION: adds an object to the specified area
*
* By: Raymond Cypher
*
* HISTORY:
*
*/
void S4FUNCTION area4add_object( AREA4 *area, OBJ4 *obj_add )
{
POBJ4 pObj, pObjnext;
int i, j;
if( !area || !obj_add )
return;
obj_add->container = NULL;
area4insert_object( &area->objects, obj_add );
if( obj_add->x == 0 && obj_add->y == 0 && obj_add->w == 0 && obj_add->h == 0 )
return;
pObj = (POBJ4)l4first( &area->objects );
j = area->objects.n_link;
i = 0;
while( pObj && i < j )
{
pObjnext = (POBJ4)l4next( &area->objects, pObj );
if( pObj->x > obj_add->x && pObj->y > obj_add->y &&
pObj->w + pObj->x < obj_add->w + obj_add->x &&
pObj->h + pObj->y < obj_add->h + obj_add->y )
{
l4remove( &area->objects, pObj );
area4insert_object( &area->objects, pObj );
}
pObj = pObjnext;
i++;
}
}
/************************************************************
** Function: area4sort_obj_tree()
*
* PARAMETERS: PAREA4 area - pointer to the AREA4 struct containing the
* objects to be sorted
*
* DESCRIPTION: sorts the objects in the areas object tree
*
* By: Raymond Cypher
*
* HISTORY:
*
*/
void S4FUNCTION area4sort_obj_tree( PAREA4 area )
{
POBJ4 obj_on;
area4sort_list( &area->objects );
obj_on = (POBJ4)l4first( &area->objects );
while( obj_on )
{
if( obj_on->contained.n_link > 0 )
area4sort_list( &obj_on->contained );
obj_on = (POBJ4)l4next( &area->objects, obj_on );
}
}
/************************************************************
** Function: area4pageBreak()
*
* PARAMETERS: PAREA4 area - area to toggle break flag of
* int breaks - new value for flag
*
* DESCRIPTION: toggles the flag allowing page breaks within the area
*
* RETURNS: the previous value of the flag
*
* By: Raymond Cypher
*
* HISTORY:
*
*/
int S4FUNCTION area4pageBreak( PAREA4 area, int breaks )
{
int temp;
if( area == NULL || breaks < 0 )
{
if( area )
e4describe( area->report->code_base, e4parm, E4_REP_PGBRK, 0, 0 );
return -1;
}
temp = area->allow_pagebreaks;
area->allow_pagebreaks = breaks;
return temp;
}
/****************************************************************************
The rest of the functions contained in this file are documented in the
CodeReporter manual.
*/
PAREA4 S4FUNCTION group4headerFirst( PGROUP4 group )
{
if( !group )
return NULL;
return (PAREA4)l4first( &group->header_areas );
}
PAREA4 S4FUNCTION group4headerNext( PGROUP4 group, PAREA4 area )
{
if( !group )
return NULL;
return (PAREA4)l4next( &group->header_areas, area );
}
PAREA4 S4FUNCTION group4headerLast( PGROUP4 group )
{
if( !group )
return NULL;
return (PAREA4)l4last( &group->header_areas );
}
PAREA4 S4FUNCTION group4headerPrev( PGROUP4 group, PAREA4 area )
{
if( !group )
return NULL;
return (PAREA4)l4prev( &group->header_areas, area );
}
int S4FUNCTION group4numHeaders( PGROUP4 group )
{
if( !group )
return 0;
return group->header_areas.n_link;
}
PAREA4 S4FUNCTION group4footerFirst( PGROUP4 group )
{
if( !group )
return NULL;
return (PAREA4)l4first( &group->footer_areas );
}
PAREA4 S4FUNCTION group4footerNext( PGROUP4 group, PAREA4 area )
{
if( !group )
return NULL;
return (PAREA4)l4next( &group->footer_areas, area );
}
PAREA4 S4FUNCTION group4footerLast( PGROUP4 group )
{
if( !group )
return NULL;
return (PAREA4)l4last( &group->footer_areas );
}
PAREA4 S4FUNCTION group4footerPrev( PGROUP4 group, PAREA4 area )
{
if( !group )
return NULL;
return (PAREA4)l4prev( &group->footer_areas, area );
}
int S4FUNCTION group4numFooters( PGROUP4 group )
{
if( !group )
return 0;
return group->footer_areas.n_link;
}
POBJ4 S4FUNCTION area4objFirst( PAREA4 area )
{
if( !area )
{
return NULL;
}
return (POBJ4)l4first( &area->objects );
}
POBJ4 S4FUNCTION area4objNext( PAREA4 area, POBJ4 aobj )
{
POBJ4 next_obj, obj;
if( !area || !aobj )
{
if( area && !aobj )
e4describe( area->report->code_base, e4parm, E4_REP_OBJNXT, 0, 0 );
return NULL;
}
obj = aobj;
if( obj->contained.n_link > 0 )
{
return (POBJ4)l4first( &obj->contained );
}
for( ;; )
{
if( !obj )
return obj;
if( obj->container == 0 )
{
return (POBJ4)l4next( &area->objects, obj );
}
next_obj = (POBJ4)l4next( &obj->container->contained, obj );
if( next_obj )
return next_obj;
obj = obj->container;
}
}
POBJ4 S4FUNCTION area4objPrev( PAREA4 area, POBJ4 aobj )
{
POBJ4 prev_obj, obj;
if( !area || !aobj )
{
if( area && !aobj )
e4describe( area->report->code_base, e4parm, E4_REP_OBJPRV, 0, 0 );
return NULL;
}
prev_obj = area4objFirst( area );
if( prev_obj == aobj )
return NULL;
obj = area4objNext( area, prev_obj );
while( obj && obj != aobj )
{
prev_obj = obj;
obj = area4objNext( area, prev_obj );
}
return prev_obj;
}
POBJ4 S4FUNCTION area4objLast( PAREA4 area )
{
POBJ4 obj, prev_obj;
if( !area )
{
return NULL;
}
prev_obj = area4objFirst( area );
obj = area4objNext( area, prev_obj );
while( obj != NULL )
{
prev_obj = obj;
obj = area4objNext( area, prev_obj );
}
return prev_obj;
}
int S4FUNCTION area4numObjects( PAREA4 area )
{
int objcount;
POBJ4 obj;
if( !area )
{
return -1;
}
objcount = 0;
obj = area4objFirst( area );
while( obj )
{
objcount++;
obj = area4objNext( area, obj );
}
return objcount;
}