/*	RSCFIX.C	09/16/86		Ric Clayton	*/
/*	STCREATE.c	04/20/85		ATARI		*/
/*	RSCREATE.C	05/18/84 - 11/01/84	LKW		*/
/*	Fix something	12/10/84 - 12/10/84	Derek Mui	*/
/*	Fix the  size	12/17/84				*/
/*	For ST		04/20/85		Derek Mui	*/
/*	For code resident rsc 09/16/86		Ric Clayton	*/

/*****************************************************************************\
*	rcsfix.doc 
*
*  RSCFIX.C -- A resource fixer for code-resident resources.
*  
*  RSCFIX.C  contains  a set of routines to prepare  a  code-resident 
*  resource  for use.   It was derived from STCREATE.C,  found in the 
*  RSCREATE  folder  on  the Resource Disk supplied  with  the  Atari 
*  Developer's Kit.
*  
*  The  routines are driven by a main routine,  rsc_fix(),  which you 
*  call  during your program initialization to prepare the  resource.  
*  The  routines perform 2 distinct functions on the  resource.   The 
*  first is to change all the offsets,  generated by RSC,  to address 
*  pointers.   The  second  function  is  to change  all  the  object 
*  rectangle  coordinates  and  sizes  from  characters  to   pixels, 
*  according to the current screen resolution.
*  
*  First  get  the download the file RSCFIX.C and put  it  with  your 
*  header  files. (e.g.  on  the compiler disk with  ALCYON,  in  the 
*  HEADERS  folder with Megamax,  in the INCLUDE folder with  Micro-C 
*  Shell and Mark Williams C, etc.)
*  
*  Next,  create  the  C source file using RCS or RCS2.   To do this, 
*  run  the RCS program,  Open your resource file,  select the Output 
*  option  from the Global menu,  select '.H' and '.C' ('.C' & '.RSH' 
*  for RCS2),  click on OK,  and Close your resource.   Put the these 
*  files with your source file(s).
*  
*  Then,  modify  your source file to include the resource's C source 
*  and header files and 'RSCFIX.C'.   Change your call to rsrc_load() 
*  to  rsc_fix().   Change  your call to rsrc_gaddr to load the  tree 
*  pointer from the rs_trindex[] array.
*  
*  Limitations:   The  'adj' macro takes care of objects that are not 
*  character  aligned but seems to have trouble when the root  object 
*  of a tree is NOT character aligned.   Just make sure all your root 
*  objects  are  character  aligned  and  you  should  not  have  any 
*  problems.
*  
*  The following code fragment illustrates the use of rsc_fix().
*  
*  #include <obdefs.h>
*  #include <gemdefs.h>
*  .
*  .
*  .
*  #ifndef BYTE                  / Take care of 'portability' / 
*  #define BYTE char             / macros in the '.RSH' file. /
*  #define WORD int
*  #define LONG long
*  #endif
*  
*  #include "resource.h"         / The header file from RSC   /
*  #include "resource.rsh"       / The C source file from RSC /
*  
*  OBJECT *tree;                 / Pointer to an object tree  /
*  .
*  .
*  / global declarations /
*  .
*  .
*  #include <rscfix.c>           / Code to fixup resource     /
*  
*  void    sort(v,n)
*  char    *v[];
*  int     n;
*          {
*          .
*          .
*          }
*  .
*  .
*  .
*  void    do_form( rsc_tree, exit_obj )
*  int     rsc_tree;
*  int     exit_obj;
*          {
*          int     xdial, ydial, wdial, hdial;
*          int     x, y, w, h;
*          int     object;
*  
*          tree = (OBJECT *) rs_trindex[ rsc_tree ];
*  
*          form_center( tree, &xdial, &ydial, &wdial, &hdial );
*          x = xdial + wdial/2;
*          y = ydial + hdial/2;
*          w = gl_wbox;
*          h = gl_hbox;
*          form_dial( 0, x, y, w, h, xdial, ydial, wdial, hdial );
*          form_dial( 1, x, y, w, h, xdial, ydial, wdial, hdial );
*  
*          objc_draw( tree, ROOT, MAX_DEPTH, xdial, ydial, wdial, hdial );
*  
*          object = 0;
*  
*          while( object != exit_obj )
*                  {
*                  object = form_do( tree, 0 ) & 0x7FFF;
*                  handle_object( tree, object );
*                  .
*                  .
*                  .
*                  }
*  
*          form_dial( 2, x, y, w, h, xdial, ydial, wdial, hdial );
*          form_dial( 3, x, y, w, h, xdial, ydial, wdial, hdial );
*          }
*  
*  main()
*          {
*          if ( appl_init() >= 0 )
*                  {
*                  rsc_fix();
*                  .
*                  .
*                  graf_mouse( M_ON, 0x0L );
*                  graf_mouse( ARROW, 0x0L );
*                  do_form( TREE0, OKBUTTON );
*                  .
*                  .
*                  appl_exit();
*                  }
*          }
*  
\*****************************************************************************/

/* rcsfix.c */
#include <aesbind.h>
#include <gemfast.h>

#ifndef BYTE                    /* Take care of 'portability' */ 
typedef char 	      BYTE;     /* macros in the '.RSH' file. */
typedef short         WORD;	/* i absolutely refuse to use */
typedef unsigned long LONG;   	/* silly includes like portab.h */
#define NIL  	      (-1L)
#endif

#include "fastbenh.h"         /* The header file from RSC   */
#include "fastbenh.rsh"       /* The C source file from RSC */

#define adj(xywh, siz) \
    (siz * ((xywh) & 0x00FF) + (((unsigned short)(xywh)) >> 8))

static void fix_trindex()
{
    int	test, ii;
    
    for (ii = 0; ii < NUM_TREE; ii++)
    {
	test = (int) rs_trindex[ii];
	rs_trindex[ii] = (LONG) &rs_object[test];
    }
}

static void fix_str(where)
long	*where;
{
    if (*where != NIL)
	*where = (long) rs_strings[*where];
}

static void fix_objects()
{
    int	 ii;
    long test;
    int	wchar, hchar;
    
    graf_handle( &wchar, &hchar, &ii, &ii );
    
    for (ii = 0; ii < NUM_OBS; ii++)
    {
	rs_object[ii].ob_x = adj(rs_object[ii].ob_x, wchar);
	rs_object[ii].ob_y = adj(rs_object[ii].ob_y, hchar);
	rs_object[ii].ob_width = adj(rs_object[ii].ob_width, wchar);
	rs_object[ii].ob_height = adj(rs_object[ii].ob_height, hchar);
	test = (long) rs_object[ii].ob_spec;
	
	switch (rs_object[ii].ob_type)
	{
	  case G_TITLE:
	  case G_STRING:
	  case G_BUTTON:
	    fix_str(&rs_object[ii].ob_spec);
	    break;
	  case G_TEXT:
	  case G_BOXTEXT:
	  case G_FTEXT:
	  case G_FBOXTEXT:
	    if (test != NIL)
		rs_object[ii].ob_spec =
		    (LONG) &rs_tedinfo[test];
	    break;
	  case G_ICON:
	    if (test != NIL)
		rs_object[ii].ob_spec =
		    (LONG) &rs_iconblk[test];
	    break;
	  case G_IMAGE:
	    if (test != NIL)
		rs_object[ii].ob_spec =
		    (LONG) &rs_bitblk[test];
	    break;
	    
	    default:
	    break;
	} /* switch */
    } /* for */
}

static void fix_tedinfo()
{
    int	ii;
    
    for (ii = 0; ii < NUM_TI; ii++)
    {
	fix_str(&rs_tedinfo[ii].te_ptext);
	fix_str(&rs_tedinfo[ii].te_ptmplt);
	fix_str(&rs_tedinfo[ii].te_pvalid);
    }
}

static void fix_frstr()
{
    int	ii;
    
    for (ii = 0; ii < NUM_FRSTR; ii++)
	fix_str(&rs_frstr[ii]);
}

static void fix_img(where)
long	*where;
{
    if (*where != NIL)
	*where = (long) (char *) rs_imdope[(int) *where].image;
}

static void fix_iconblk()
{
    int	ii;
    
    for (ii = 0; ii < NUM_IB; ii++)
    {
	fix_img(&rs_iconblk[ii].ib_pmask);
	fix_img(&rs_iconblk[ii].ib_pdata);
	fix_str(&rs_iconblk[ii].ib_ptext);
    }
}

static void fix_bitblk()
{
    int	ii;
    
    for (ii = 0; ii < NUM_BB; ii++)
	fix_img(&rs_bitblk[ii].bi_pdata);
}

static void fix_bb(where)
long	*where;
{
    if (*where != NIL)
	*where = (long) (char *) &rs_bitblk[(char) *where];
}

static void fix_frimg()
{
    int	ii;
    
    for (ii = 0; ii < NUM_FRIMG; ii++)
	fix_bb(&rs_frimg[ii]);
}


/* this is the only 'exported' function in
 * this module.
 */
void rsc_fix()
{
    fix_trindex();
    fix_objects();
    fix_tedinfo();
    fix_iconblk();
    fix_bitblk();
    fix_frstr();
    fix_frimg();
}

#undef adj
