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;
 | 
						|
}
 |