which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@976 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			625 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			625 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* 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;
 | |
| }
 |